diff --git a/CHANGELOG.md b/CHANGELOG.md index 873166aed..8b2f2de6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +15.10.2020 +* Tara integration for registrant portal [#1698](https://github.com/internetee/registry/pull/1698) + +14.10.2020 +* Added company registration data query to regisrant API [#1708](https://github.com/internetee/registry/issues/1708) +* Fixed domain delete history records in admin [#1710](https://github.com/internetee/registry/issues/1710) + +09.10.2020 +* Fixed pendingUpdate release while forceDelete is set [#1705](https://github.com/internetee/registry/issues/1705) + +08.10.2020 +* Fixed serach in admin history [#1695](https://github.com/internetee/registry/issues/1695) + +06.10.2020 +* Updated Directo gem to fix vat codes for EU and non-EU clients [#1699](https://github.com/internetee/registry/pull/1699) +* Email validation level is now configurable [#1675](https://github.com/internetee/registry/pull/1675) + 01.10.2020 * Fixed EPP authentication [#1697](https://github.com/internetee/registry/pull/1697) diff --git a/Gemfile b/Gemfile index 34bc9b7ac..da5ae00cf 100644 --- a/Gemfile +++ b/Gemfile @@ -66,7 +66,8 @@ gem 'pdfkit' gem 'jquery-ui-rails', '5.0.5' gem 'airbrake' -gem 'company_register', github: 'internetee/company_register', branch: :master +gem 'company_register', github: 'internetee/company_register', + branch: 'master' gem 'e_invoice', github: 'internetee/e_invoice', branch: :master gem 'lhv', github: 'internetee/lhv', branch: 'master' gem 'domain_name' diff --git a/Gemfile.lock b/Gemfile.lock index ff6dcd3a3..c92eaa3d8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/internetee/company_register.git - revision: 86d691997aa7def9f86d88f6c92cabb86cd65487 + revision: 4181b2fff9080e2d87d15612561131f9e3fdfb4c branch: master specs: company_register (0.1.0) @@ -9,7 +9,7 @@ GIT GIT remote: https://github.com/internetee/directo.git - revision: e4ba54f601d1815fd8782a196788730d47861e86 + revision: 711ce2d942456ee830b649b03b7141e903a1d86b branch: master specs: directo (1.0.1) diff --git a/app/controllers/api/v1/registrant/companies_controller.rb b/app/controllers/api/v1/registrant/companies_controller.rb new file mode 100644 index 000000000..b11c06909 --- /dev/null +++ b/app/controllers/api/v1/registrant/companies_controller.rb @@ -0,0 +1,52 @@ +require 'serializers/registrant_api/company' + +module Api + module V1 + module Registrant + class CompaniesController < ::Api::V1::Registrant::BaseController + MAX_LIMIT = 200 + MIN_OFFSET = 0 + + def index + result = error_result('limit') if limit > MAX_LIMIT || limit < 1 + result = error_result('offset') if offset < MIN_OFFSET + result ||= companies_result(limit, offset) + + render result + end + + def current_user_companies + current_registrant_user.companies + rescue CompanyRegister::NotAvailableError + [] + end + + def limit + (params[:limit] || MAX_LIMIT).to_i + end + + def offset + (params[:offset] || MIN_OFFSET).to_i + end + + def error_result(attr_name) + { json: { errors: [{ attr_name.to_sym => ['parameter is out of range'] }] }, + status: :bad_request } + end + + def companies_result(limit, offset) + @companies = current_user_companies.drop(offset).first(limit) + status = @companies.present? ? :ok : :not_found + + serialized_companies = @companies.map do |item| + country_code = current_registrant_user.country.alpha3 + serializer = ::Serializers::RegistrantApi::Company.new(company: item, + country_code: country_code) + serializer.to_json + end + { json: { companies: serialized_companies }, status: status } + end + end + end + end +end diff --git a/app/controllers/registrant/sessions_controller.rb b/app/controllers/registrant/sessions_controller.rb index b18a802e6..73b6d52da 100644 --- a/app/controllers/registrant/sessions_controller.rb +++ b/app/controllers/registrant/sessions_controller.rb @@ -1,81 +1,6 @@ class Registrant::SessionsController < Devise::SessionsController layout 'registrant/application' - def login_mid - @user = User.new - end - - 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'} - 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 - end - - @user = RegistrantUser.find_or_create_by_mid_data(response) - - if @user.persisted? - session[:user_country] = response.user_country - 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 - - 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 = RegistrantUser.find_by(registrant_ident: "#{session[:user_country]}-#{session[:user_id_code]}") - - sign_in(:registrant_user, @user) - flash[:notice] = t(:welcome) - flash.keep(:notice) - render js: "window.location = '#{registrant_root_path}'" - 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 - private def after_sign_in_path_for(_resource_or_scope) diff --git a/app/controllers/registrar/tara_controller.rb b/app/controllers/registrar/tara_controller.rb deleted file mode 100644 index e02aa52a5..000000000 --- a/app/controllers/registrar/tara_controller.rb +++ /dev/null @@ -1,33 +0,0 @@ -class Registrar - class TaraController < ApplicationController - skip_authorization_check - - # rubocop:disable Style/AndOr - def callback - session[:omniauth_hash] = user_hash - @api_user = ApiUser.from_omniauth(user_hash) - - if @api_user - flash[:notice] = t(:signed_in_successfully) - sign_in_and_redirect(:registrar_user, @api_user) - else - show_error and return - end - end - # rubocop:enable Style/AndOr - - def cancel - redirect_to root_path, notice: t(:sign_in_cancelled) - end - - def show_error - redirect_to new_registrar_user_session_url, alert: t(:no_such_user) - end - - private - - def user_hash - request.env['omniauth.auth'] - end - end -end diff --git a/app/controllers/sso/tara_controller.rb b/app/controllers/sso/tara_controller.rb new file mode 100644 index 000000000..37c8ab608 --- /dev/null +++ b/app/controllers/sso/tara_controller.rb @@ -0,0 +1,40 @@ +module Sso + class TaraController < ApplicationController + skip_authorization_check + + def registrant_callback + user = RegistrantUser.find_or_create_by_omniauth_data(user_hash) + callback(user, registrar: false) + end + + def registrar_callback + user = ApiUser.from_omniauth(user_hash) + callback(user, registrar: true) + end + + # rubocop:disable Style/AndOr + def callback(user, registrar: true) + session[:omniauth_hash] = user_hash + (show_error(registrar: registrar) and return) unless user + + flash[:notice] = t(:signed_in_successfully) + sign_in_and_redirect(registrar ? :registrar_user : :registrant_user, user) + end + # rubocop:enable Style/AndOr + + def cancel + redirect_to root_path, notice: t(:sign_in_cancelled) + end + + def show_error(registrar: true) + path = registrar ? new_registrar_user_session_url : new_registrant_user_session_url + redirect_to path, alert: t(:no_such_user) + end + + private + + def user_hash + request.env['omniauth.auth'] + end + end +end diff --git a/app/models/api_user.rb b/app/models/api_user.rb index 8159137a3..61dd12387 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -47,12 +47,6 @@ class ApiUser < User self.active = true unless saved_change_to_active? end - class << self - def find_by_id_card(id_card) - find_by(identity_code: id_card.personal_code) - end - end - def to_s username end diff --git a/app/models/domain.rb b/app/models/domain.rb index 679669728..391c9c030 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -489,7 +489,7 @@ class Domain < ApplicationRecord end def pending_update? - statuses.include?(DomainStatus::PENDING_UPDATE) && !statuses.include?(DomainStatus::FORCE_DELETE) + statuses.include?(DomainStatus::PENDING_UPDATE) end # depricated not used, not valid diff --git a/app/models/id_card.rb b/app/models/id_card.rb deleted file mode 100644 index 0e3c11bb3..000000000 --- a/app/models/id_card.rb +++ /dev/null @@ -1,6 +0,0 @@ -class IdCard - attr_accessor :first_name - attr_accessor :last_name - attr_accessor :personal_code - attr_accessor :country_code -end \ No newline at end of file diff --git a/app/models/registrant_user.rb b/app/models/registrant_user.rb index 7bd84d5dd..c0addb5cd 100644 --- a/app/models/registrant_user.rb +++ b/app/models/registrant_user.rb @@ -1,7 +1,7 @@ class RegistrantUser < User attr_accessor :idc_data - devise :trackable, :timeoutable, :id_card_authenticatable + devise :trackable, :timeoutable def ability @ability ||= Ability.new(self) @@ -66,23 +66,19 @@ class RegistrantUser < User find_or_create_by_user_data(user_data) end - def find_or_create_by_mid_data(response) - user_data = { first_name: response.user_givenname, last_name: response.user_surname, - ident: response.user_id_code, country_code: response.user_country } + def find_or_create_by_omniauth_data(omniauth_hash) + uid = omniauth_hash['uid'] + identity_code = uid.slice(2..-1) + country_code = uid.slice(0..1) + first_name = omniauth_hash.dig('info', 'first_name') + last_name = omniauth_hash.dig('info', 'last_name') + + user_data = { first_name: first_name, last_name: last_name, + ident: identity_code, country_code: country_code } find_or_create_by_user_data(user_data) end - def find_by_id_card(id_card) - registrant_ident = "#{id_card.country_code}-#{id_card.personal_code}" - username = [id_card.first_name, id_card.last_name].join("\s") - - user = find_or_initialize_by(registrant_ident: registrant_ident) - user.username = username - user.save! - user - end - private def find_or_create_by_user_data(user_data = {}) diff --git a/app/views/admin/domain_versions/archive.haml b/app/views/admin/domain_versions/archive.haml index 9fdf8b000..f813f5eb3 100644 --- a/app/views/admin/domain_versions/archive.haml +++ b/app/views/admin/domain_versions/archive.haml @@ -57,7 +57,7 @@ - if version - attributes = only_present_fields(version, Domain) - domain = Domain.new(attributes) - - attach_existing_fields(version, domain) + - attach_existing_fields(version, domain) unless version.event == 'destroy' %tr %td= link_to(domain.name, admin_domain_version_path(version.id)) @@ -67,7 +67,7 @@ - else - contact = Contact.all_versions_for([domain.registrant_id], version.created_at).first - if contact.nil? && ver = ContactVersion.where(item_id: domain.registrant_id).last - - contact = Contact.new(ver.object.to_h.merge(ver.object_changes.to_h.each_with_object({}){|(k,v), o| o.public_send("#{k}=", v.last) } )) + - contact = Contact.new(ver.object.to_h.merge(ver.object_changes.to_h.each_with_object({}) {|(k,v), o| o[k] = v.last })) = contact.try(:name) = " ".html_safe = "(#{t(:deleted)})" diff --git a/app/views/admin/domain_versions/show.haml b/app/views/admin/domain_versions/show.haml index cb95f231c..11f70599f 100644 --- a/app/views/admin/domain_versions/show.haml +++ b/app/views/admin/domain_versions/show.haml @@ -1,6 +1,6 @@ - present_fields = only_present_fields(@version, Domain) - domain = Domain.new(present_fields) -- attach_existing_fields(@version, domain) +- attach_existing_fields(@version, domain) unless @version.event == 'destroy' - if @version - children = HashWithIndifferentAccess.new(@version.children) diff --git a/app/views/registrant/sessions/login_mid.haml b/app/views/registrant/sessions/login_mid.haml deleted file mode 100644 index 318e19033..000000000 --- a/app/views/registrant/sessions/login_mid.haml +++ /dev/null @@ -1,40 +0,0 @@ -.row - .form-signin.col-md-4.center-block.text-center - %h2.form-signin-heading.text-center= t '.header' - %hr - = form_for @user, url: registrant_mid_path, html: {class: 'form-signin'} do |f| - = f.text_field :phone, class: 'form-control', - placeholder: t(:phone_no), autocomplete: 'off', required: true - %button.btn.btn-lg.btn-primary.btn-block.js-login{:type => 'submit'}= t '.submit_btn' - - - if ['development', 'alpha'].include?(Rails.env) - %div.text-center - 00007, 60000007, 00000766 - -:coffee - load_listener = -> - $('.js-login').attr('disabled', false) - - status_interval = null - mid_status = () -> - status_interval = setInterval((-> - $.post('/registrant/login/mid_status').fail((data) -> - clearInterval(status_interval) - flash_alert(data.responseJSON.message) - $('.js-login').attr('disabled', false) - ) - ), 1000) - - $('.js-login').on 'click', (e) -> - e.preventDefault(); - $(this).attr('disabled', true) - - $.post($('form').attr('action'), $('form').serialize()).done((data) -> - if data.message - flash_notice(data.message) - mid_status() - ).fail((data) -> - flash_alert(data.responseJSON.message) - $('.js-login').attr('disabled', false) - ) - window.addEventListener 'load', load_listener diff --git a/app/views/registrant/sessions/new.html.erb b/app/views/registrant/sessions/new.html.erb index a3203e83a..9f7af3254 100644 --- a/app/views/registrant/sessions/new.html.erb +++ b/app/views/registrant/sessions/new.html.erb @@ -8,11 +8,6 @@ <%= t '.hint' %>
- <%= link_to '/registrant/login/mid' do %> - <%= image_tag 'mid.gif' %> - <% end %> - <%= link_to registrant_id_card_sign_in_path, method: :post do %> - <%= image_tag 'id_card.gif' %> - <% end %> + <%= link_to t(:sign_in), "/auth/rant_tara", method: :post, class: 'btn btn-lg btn-primary btn-block' %> - \ No newline at end of file + diff --git a/app/views/registrar/sessions/login_mid.haml b/app/views/registrar/sessions/login_mid.haml deleted file mode 100644 index 7ee604209..000000000 --- a/app/views/registrar/sessions/login_mid.haml +++ /dev/null @@ -1,40 +0,0 @@ -.row - .form-signin.col-md-4.center-block.text-center - %h2.form-signin-heading.text-center= t '.header' - %hr - = form_for @user, url: registrar_mid_path, html: {class: 'form-signin'} do |f| - = f.text_field :phone, class: 'form-control', - placeholder: t(:phone_no), autocomplete: 'off', required: true - %button.btn.btn-lg.btn-primary.btn-block.js-login{:type => 'submit'}= t '.submit_btn' - - - if ['development', 'alpha'].include?(Rails.env) - %div.text-center - 00007, 60000007, 00000766 - -:coffee - load_listener = -> - $('.js-login').attr('disabled', false) - - status_interval = null - mid_status = () -> - status_interval = setInterval((-> - $.post('/registrar/login/mid_status').fail((data) -> - clearInterval(status_interval) - flash_alert(data.responseJSON.message) - $('.js-login').attr('disabled', false) - ) - ), 1000) - - $('.js-login').on 'click', (e) -> - e.preventDefault(); - $(this).attr('disabled', true) - - $.post($('form').attr('action'), $('form').serialize()).done((data) -> - if data.message - flash_notice(data.message) - mid_status() - ).fail((data) -> - flash_alert(data.responseJSON.message) - $('.js-login').attr('disabled', false) - ) - window.addEventListener 'load', load_listener diff --git a/config/application.yml.sample b/config/application.yml.sample index cbe32e5db..ab64ed35e 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -163,6 +163,13 @@ tara_secret: 'secret' tara_redirect_uri: 'redirect_url' tara_keys: "{\"kty\":\"RSA\",\"kid\":\"de6cc4\",\"n\":\"jWwAjT_03ypme9ZWeSe7c-jY26NO50Wo5I1LBnPW2JLc0dPMj8v7y4ehiRpClYNTaSWcLd4DJmlKXDXXudEUWwXa7TtjBFJfzlZ-1u0tDvJ-H9zv9MzO7UhUFytztUEMTrtStdhGbzkzdEZZCgFYeo2i33eXxzIR1nGvI05d9Y-e_LHnNE2ZKTa89BC7ZiCXq5nfAaCgQna_knh4kFAX-KgiPRAtsiDHcAWKcBY3qUVcb-5XAX8p668MlGLukzsh5tFkQCbJVyNtmlbIHdbGvVHPb8C0H3oLYciv1Fjy_tS1lO7OT_cb3GVp6Ql-CG0uED_8pkpVtfsGRviub4_ElQ\",\"e\":\"AQAB\"}" +tara_rant_identifier: 'identifier' +tara_rant_secret: 'secret' +tara_rant_redirect_uri: 'redirect_uri' + +default_email_validation_type: 'regex' + + # Since the keys for staging are absent from the repo, we need to supply them separate for testing. test: payments_seb_bank_certificate: 'test/fixtures/files/seb_bank_cert.pem' diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index dee2824a4..eb0465796 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -280,10 +280,4 @@ Devise.setup do |config| # When using OmniAuth, Devise cannot automatically set OmniAuth path, # so you need to do it manually. For the users scope, it would be: # config.omniauth_path_prefix = '/my_engine/users/auth' - - require 'devise/models/id_card_authenticatable' - require 'devise/strategies/id_card_authenticatable' - - routes = [nil, :new, :destroy] - config.add_module :id_card_authenticatable, strategy: true, route: { session: routes } end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index ef5350384..e3e0d644b 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -16,6 +16,10 @@ identifier = ENV['tara_identifier'] secret = ENV['tara_secret'] redirect_uri = ENV['tara_redirect_uri'] +registrant_identifier = ENV['tara_rant_identifier'] +registrant_secret = ENV['tara_rant_secret'] +registrant_redirect_uri = ENV['tara_rant_redirect_uri'] + Rails.application.config.middleware.use OmniAuth::Builder do provider "tara", { callback_path: '/registrar/open_id/callback', @@ -43,4 +47,30 @@ Rails.application.config.middleware.use OmniAuth::Builder do redirect_uri: redirect_uri, }, } + + provider "tara", { + callback_path: '/registrant/open_id/callback', + name: 'rant_tara', + scope: ['openid'], + client_signing_alg: :RS256, + client_jwk_signing_key: signing_keys, + send_scope_to_token_endpoint: false, + send_nonce: true, + issuer: issuer, + + client_options: { + scheme: 'https', + host: host, + + authorization_endpoint: '/oidc/authorize', + token_endpoint: '/oidc/token', + userinfo_endpoint: nil, # Not implemented + jwks_uri: '/oidc/jwks', + + # Registry + identifier: registrant_identifier, + secret: registrant_secret, + redirect_uri: registrant_redirect_uri, + }, + } end diff --git a/config/initializers/truemail.rb b/config/initializers/truemail.rb index f4517fbc0..ecab32ced 100644 --- a/config/initializers/truemail.rb +++ b/config/initializers/truemail.rb @@ -28,7 +28,10 @@ Truemail.configure do |config| # Optional parameter. You can predefine default validation type for # Truemail.validate('email@email.com') call without with-parameter # Available validation types: :regex, :mx, :smtp - if Rails.env.production? + if ENV['default_email_validation_type'].present? && + %w[regex mx smtp].include?(ENV['default_email_validation_type']) + config.default_validation_type = ENV['default_email_validation_type'].to_sym + elsif Rails.env.production? config.default_validation_type = :mx else config.default_validation_type = :regex diff --git a/config/locales/registrant/sessions.en.yml b/config/locales/registrant/sessions.en.yml index 3032382c1..7d4c16da9 100644 --- a/config/locales/registrant/sessions.en.yml +++ b/config/locales/registrant/sessions.en.yml @@ -2,11 +2,7 @@ en: registrant: sessions: new: - header: Log in + header: Sign in with identity document hint: >- - Access currently available only to Estonian citizens and e-residents with Estonian ID-card - or Mobile-ID. - - login_mid: - header: Log in with mobile-id - submit_btn: Login \ No newline at end of file + Sign in using Estonian (incl. e-residents) ID card, mobile ID, + Bank link or other EU citizen's electronic ID supported by EIDAS. diff --git a/config/routes.rb b/config/routes.rb index 282a44933..4eb09544f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,9 +91,11 @@ Rails.application.routes.draw do resource :registry_lock, only: %i[create destroy] end resources :contacts, only: %i[index show update], param: :uuid + resources :companies, only: %i[index] end resources :auctions, only: %i[index show update], param: :uuid + end match '*all', controller: 'cors', action: 'cors_preflight_check', via: [:options], @@ -106,12 +108,6 @@ Rails.application.routes.draw do devise_for :users, path: '', class_name: 'ApiUser', skip: %i[sessions] - devise_scope :registrar_user do - match '/open_id/callback', via: %i[get post], to: 'tara#callback', as: :tara_callback - match '/open_id/cancel', via: %i[get post delete], to: 'tara#cancel', - as: :tara_cancel - end - resources :invoices, except: %i[new create edit update destroy] do resource :delivery, controller: 'invoices/delivery', only: %i[new create] @@ -188,6 +184,22 @@ Rails.application.routes.draw do post 'sessions', to: 'registrar/sessions#create', as: :registrar_user_session delete 'sign_out', to: 'registrar/sessions#destroy', as: :destroy_registrar_user_session + + # TARA + match '/open_id/callback', via: %i[get post], to: 'sso/tara#registrar_callback' + match '/open_id/cancel', via: %i[get post delete], to: 'sso/tara#cancel' + end + end + + scope :registrant do + devise_scope :registrant_user do + get 'sign_in', to: 'registrant/sessions#new', as: :new_registrant_user_session + post 'sessions', to: 'registrant/sessions#create', as: :registrant_user_session + delete 'sign_out', to: 'registrant/sessions#destroy', as: :destroy_registrant_user_session + + # TARA + match '/open_id/callback', via: %i[get post], to: 'sso/tara#registrant_callback' + match '/open_id/cancel', via: %i[get post delete], to: 'sso/tara#cancel' end end @@ -196,19 +208,9 @@ Rails.application.routes.draw do # POST /registrant/sign_in is not used devise_for :users, path: '', class_name: 'RegistrantUser' - devise_scope :registrant_user do - get 'login/mid' => 'sessions#login_mid' - post 'login/mid' => 'sessions#mid' - post 'login/mid_status' => 'sessions#mid_status' - post 'mid' => 'sessions#mid' - - # /registrant/id path is hardcoded in Apache config for authentication with Estonian ID-card - # Client certificate is asked only on login form submission, therefore the path must be different from the one in - # `new_registrant_user_session_path` route, in case some other auth type will be implemented - post 'id' => 'sessions#create', as: :id_card_sign_in - end resources :registrars, only: :show + # resources :companies, only: :index resources :domains, only: %i[index show] do resources :contacts, only: %i[show edit update] member do diff --git a/doc/registrant-api/v1/companies.md b/doc/registrant-api/v1/companies.md new file mode 100644 index 000000000..2804a63c8 --- /dev/null +++ b/doc/registrant-api/v1/companies.md @@ -0,0 +1,34 @@ +## GET /api/v1/registrant/companies +Returns list of companies registered in business register for the current registrant. + + +#### Parameters + +| Field name | Required | Type | Allowed values | Description | +| ---------- | -------- | ---- | -------------- | ----------- | +| limit | false | Integer | [1..200] | How many companies to show | +| offset | false | Integer | | Company number to start at | + +#### Request +``` +GET /api/v1/registrant/companies?limit=1 HTTP/1.1 +Accept: application/json +Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ== +Content-Type: application/json +``` + +#### Response +``` +HTTP/1.1 200 +Content-Type: application/json + +{ + "companies":[ + { + "name":"ACME Ltd", + "registry_no":"37605030299", + "country_code":"EE" + } + ] +} +``` diff --git a/lib/devise/models/id_card_authenticatable.rb b/lib/devise/models/id_card_authenticatable.rb deleted file mode 100644 index 53bad663f..000000000 --- a/lib/devise/models/id_card_authenticatable.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Devise - module Models - # Devise fails without this module (and model: false does not help) - module IdCardAuthenticatable - end - end -end \ No newline at end of file diff --git a/lib/devise/strategies/id_card_authenticatable.rb b/lib/devise/strategies/id_card_authenticatable.rb deleted file mode 100644 index 6c3a7ac92..000000000 --- a/lib/devise/strategies/id_card_authenticatable.rb +++ /dev/null @@ -1,49 +0,0 @@ -module Devise - module Strategies - class IdCardAuthenticatable < Devise::Strategies::Authenticatable - def valid? - env['SSL_CLIENT_S_DN_CN'].present? - end - - def authenticate! - resource = mapping.to - user = resource.find_by_id_card(id_card) - - if user - success!(user) - else - fail - end - end - - private - - def id_card - id_card = IdCard.new - id_card.first_name = first_name - id_card.last_name = last_name - id_card.personal_code = personal_code - id_card.country_code = country_code - id_card - end - - def first_name - env['SSL_CLIENT_S_DN_CN'].split(',').second.force_encoding('utf-8') - end - - def last_name - env['SSL_CLIENT_S_DN_CN'].split(',').first.force_encoding('utf-8') - end - - def personal_code - env['SSL_CLIENT_S_DN_CN'].split(',').last - end - - def country_code - env['SSL_CLIENT_I_DN_C'] - end - end - end -end - -Warden::Strategies.add(:id_card_authenticatable, Devise::Strategies::IdCardAuthenticatable) diff --git a/lib/serializers/registrant_api/company.rb b/lib/serializers/registrant_api/company.rb new file mode 100644 index 000000000..d0d914cd7 --- /dev/null +++ b/lib/serializers/registrant_api/company.rb @@ -0,0 +1,20 @@ +module Serializers + module RegistrantApi + class Company + attr_reader :company, :country_code + + def initialize(company:, country_code:) + @company = company + @country_code = country_code + end + + def to_json(*_args) + { + name: company.company_name, + registry_no: company.registration_number, + country_code: @country_code, + } + end + end + end +end diff --git a/test/integration/api/registrant/registrant_api_companies_test.rb b/test/integration/api/registrant/registrant_api_companies_test.rb new file mode 100644 index 000000000..b08383796 --- /dev/null +++ b/test/integration/api/registrant/registrant_api_companies_test.rb @@ -0,0 +1,43 @@ +require 'test_helper' +require 'auth_token/auth_token_creator' + +class RegistrantApiCompaniesTest < ApplicationIntegrationTest + def setup + super + + @contact = contacts(:john) + @user = users(:registrant) + @auth_headers = { 'HTTP_AUTHORIZATION' => auth_token } + end + + def test_accepts_limit_and_offset_parameters + contacts(:william).update!(ident: '1234', ident_type: 'priv', ident_country_code: 'US') + + get '/api/v1/registrant/companies', params: { 'limit' => 1, 'offset' => 0 }, + headers: @auth_headers + response_json = JSON.parse(response.body, symbolize_names: true) + assert_equal(200, response.status) + assert_equal(1, response_json.values.flatten.count) + + get '/api/v1/registrant/companies', headers: @auth_headers + response_json = JSON.parse(response.body, symbolize_names: true) + assert_equal(@user.companies.size, response_json.count) + end + + def test_format + contacts(:william).update!(ident: '1234', ident_type: 'priv', ident_country_code: 'US') + get '/api/v1/registrant/companies', headers: @auth_headers + response_json = JSON.parse(response.body, symbolize_names: true) + assert_equal(1, response_json.count) + assert response_json.is_a?(Hash) + assert_equal(:companies, response_json.keys.first) + end + + private + + def auth_token + token_creator = AuthTokenCreator.create_with_defaults(@user) + hash = token_creator.token_in_hash + "Bearer #{hash[:access_token]}" + end +end diff --git a/test/integration/registrant_area/sign_in/id_card_test.rb b/test/integration/registrant_area/sign_in/id_card_test.rb deleted file mode 100644 index fe6c8a7ef..000000000 --- a/test/integration/registrant_area/sign_in/id_card_test.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'test_helper' - -class RegistrantAreaIdCardSignInTest < ApplicationIntegrationTest - setup do - allow_business_registry_component_reach_server - end - - def test_succeeds - post registrant_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => 'DOE,JOHN,1234', - 'SSL_CLIENT_I_DN_C' => 'US' } - follow_redirect! - - assert_response :ok - assert_equal registrant_root_path, path - assert_not_nil controller.current_registrant_user - end - - def test_fails_when_certificate_is_absent - post registrant_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => '' } - - assert_response :ok - assert_equal registrant_id_card_sign_in_path, path - assert_nil controller.current_registrant_user - end - - private - - def allow_business_registry_component_reach_server - WebMock.allow_net_connect! - end -end \ No newline at end of file diff --git a/test/lib/devise/strategies/id_card_authenticatable_test.rb b/test/lib/devise/strategies/id_card_authenticatable_test.rb deleted file mode 100644 index e194ccaac..000000000 --- a/test/lib/devise/strategies/id_card_authenticatable_test.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'test_helper' - -class IdCardAuthenticatableTest < ActiveSupport::TestCase - def test_valid_when_id_card_data_is_present_in_env - strategy = Devise::Strategies::IdCardAuthenticatable.new({ 'SSL_CLIENT_S_DN_CN' => 'some' }) - assert strategy.valid? - end - - def test_not_valid_when_id_card_data_is_absent_in_env - strategy = Devise::Strategies::IdCardAuthenticatable.new({}) - assert_not strategy.valid? - end -end \ No newline at end of file diff --git a/test/mailers/domain_delete_mailer_test.rb b/test/mailers/domain_delete_mailer_test.rb index ae060921f..b65ba5d2e 100644 --- a/test/mailers/domain_delete_mailer_test.rb +++ b/test/mailers/domain_delete_mailer_test.rb @@ -73,7 +73,7 @@ class DomainDeleteMailerTest < ActionMailer::TestCase assert_emails 1 assert_equal ['legal@registry.test'], email.from - assert_equal @domain.force_delete_contact_emails, email.to + assert @domain.force_delete_contact_emails.sort == email.to.sort assert_equal 'Domeen shop.test on kustutusmenetluses' \ ' / Domain shop.test is in deletion process' \ ' / Домен shop.test в процессе удаления', email.subject diff --git a/test/models/api_user_test.rb b/test/models/api_user_test.rb index ecbff5cbb..525e6c264 100644 --- a/test/models/api_user_test.rb +++ b/test/models/api_user_test.rb @@ -52,17 +52,6 @@ class ApiUserTest < ActiveSupport::TestCase assert ApiUser.new.active? end - def test_finds_user_by_id_card - id_card = IdCard.new - id_card.personal_code = 'one' - - @user.update!(identity_code: 'one') - assert_equal @user, ApiUser.find_by_id_card(id_card) - - @user.update!(identity_code: 'another') - assert_nil ApiUser.find_by_id_card(id_card) - end - def test_verifies_pki_status certificate = certificates(:api) diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index e3818c484..ad91ccfec 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -242,4 +242,14 @@ class NewDomainForceDeleteTest < ActiveSupport::TestCase assert_not_includes(@domain.statuses, asserted_status) end + + def test_force_delete_does_not_affect_pending_update_check + @domain.schedule_force_delete(type: :soft) + @domain.reload + + @domain.statuses << DomainStatus::PENDING_UPDATE + + assert @domain.force_delete_scheduled? + assert @domain.pending_update? + end end diff --git a/test/models/domain_cron_test.rb b/test/models/domain_cron_test.rb index 5b3b0120e..3bf36b9e2 100644 --- a/test/models/domain_cron_test.rb +++ b/test/models/domain_cron_test.rb @@ -52,4 +52,26 @@ class DomainCronTest < ActiveSupport::TestCase assert_emails 0 end + + def test_cleans_expired_pendings_when_force_delete_active + Setting.expire_pending_confirmation = 0 + + # Set force delete + @domain.schedule_force_delete(type: :soft) + @domain.reload + + @domain.statuses << DomainStatus::PENDING_UPDATE + # Set domain registrant change that's expired + @domain.update!(registrant_verification_asked_at: Time.zone.now, + registrant_verification_token: 'test', + statuses: @domain.statuses) + + assert @domain.pending_update? + @domain.reload + + DomainCron.clean_expired_pendings + @domain.reload + + assert_not @domain.pending_update? + end end diff --git a/test/models/registrant_user/registrant_user_creation_test.rb b/test/models/registrant_user/registrant_user_creation_test.rb index 42fb0e0f6..5ed680795 100644 --- a/test/models/registrant_user/registrant_user_creation_test.rb +++ b/test/models/registrant_user/registrant_user_creation_test.rb @@ -26,13 +26,4 @@ class RegistrantUserCreationTest < ActiveSupport::TestCase user = User.find_by(registrant_ident: 'EE-37710100070') assert_equal('JOHN SMITH', user.username) end - - def test_find_or_create_by_mid_data_creates_a_user - user_data = OpenStruct.new(user_country: 'EE', user_id_code: '37710100070', - user_givenname: 'JOHN', user_surname: 'SMITH') - - RegistrantUser.find_or_create_by_mid_data(user_data) - user = User.find_by(registrant_ident: 'EE-37710100070') - assert_equal('JOHN SMITH', user.username) - end end diff --git a/test/models/registrant_user_test.rb b/test/models/registrant_user_test.rb index 78b9ef901..c61f095f2 100644 --- a/test/models/registrant_user_test.rb +++ b/test/models/registrant_user_test.rb @@ -30,34 +30,6 @@ class RegistrantUserTest < ActiveSupport::TestCase assert_equal Country.new('US'), user.country end - def test_finding_by_id_card_creates_new_user_upon_first_sign_in - assert_not_equal 'US-5555', @user.registrant_ident - id_card = IdCard.new - id_card.first_name = 'John' - id_card.last_name = 'Doe' - id_card.personal_code = '5555' - id_card.country_code = 'US' - - assert_difference 'RegistrantUser.count' do - RegistrantUser.find_by_id_card(id_card) - end - - user = RegistrantUser.last - assert_equal 'US-5555', user.registrant_ident - assert_equal 'John Doe', user.username - end - - def test_finding_by_id_card_reuses_existing_user_upon_subsequent_id_card_sign_ins - @user.update!(registrant_ident: 'US-5555') - id_card = IdCard.new - id_card.personal_code = '5555' - id_card.country_code = 'US' - - assert_no_difference 'RegistrantUser.count' do - RegistrantUser.find_by_id_card(id_card) - end - end - def test_queries_company_register_for_associated_companies assert_equal 'US-1234', @user.registrant_ident @@ -92,4 +64,4 @@ class RegistrantUserTest < ActiveSupport::TestCase assert_equal %w(shop airport), @user.administered_domains end end -end \ No newline at end of file +end diff --git a/test/system/registrant_area/tara/tara_users_test.rb b/test/system/registrant_area/tara/tara_users_test.rb new file mode 100644 index 000000000..5020616d4 --- /dev/null +++ b/test/system/registrant_area/tara/tara_users_test.rb @@ -0,0 +1,51 @@ +require 'application_system_test_case' + +class RegistrantAreaTaraUsersTest < ApplicationSystemTestCase + def setup + super + + OmniAuth.config.test_mode = true + @registrant = users(:registrant) + + @existing_user_hash = { + 'provider' => 'rant_tara', + 'uid' => "US1234", + 'info': { 'first_name': 'Registrant', 'last_name': 'User' } + } + + @new_user_hash = { + 'provider' => 'rant_tara', + 'uid' => 'EE51007050604', + 'info': { 'first_name': 'New Registrant', 'last_name': 'User'} + } + end + + def teardown + super + + OmniAuth.config.test_mode = false + OmniAuth.config.mock_auth['rant_tara'] = nil + end + + def test_existing_user_gets_signed_in + OmniAuth.config.mock_auth[:rant_tara] = OmniAuth::AuthHash.new(@existing_user_hash) + + visit new_registrant_user_session_path + click_link('Sign in') + + assert_text('Signed in successfully') + end + + def test_new_user_is_created_and_signed_in + OmniAuth.config.mock_auth[:rant_tara] = OmniAuth::AuthHash.new(@new_user_hash) + + assert_difference 'RegistrantUser.count' do + visit new_registrant_user_session_path + click_link('Sign in') + + assert_equal 'New Registrant User', RegistrantUser.last.username + assert_equal 'EE-51007050604', RegistrantUser.last.registrant_ident + assert_text('Signed in successfully') + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 6e1b10c88..459d4f8f5 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -27,10 +27,10 @@ Rake::Task.clear Rails.application.load_tasks class CompanyRegisterClientStub - Company = Struct.new(:registration_number) + Company = Struct.new(:registration_number, :company_name) def representation_rights(citizen_personal_code:, citizen_country_code:) - [Company.new('1234567')] + [Company.new('1234567', 'ACME Ltd')] end end