Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added api endpoint for registrar login #2105

Merged
merged 15 commits into from
Nov 10, 2021
67 changes: 67 additions & 0 deletions app/controllers/api/v1/accreditation_center/auth_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require 'serializers/repp/domain'

module Api
module V1
module AccreditationCenter
class AuthController < ::Api::V1::AccreditationCenter::BaseController
before_action :authenticate_user

def index
login = @current_user
registrar = @current_user.registrar

# rubocop:disable Style/AndOr
render_success(data: nil) and return unless login
# rubocop:enable Style/AndOr

data = set_values_to_data(login: login, registrar: registrar)

render_success(data: data)
end

private

def authenticate_user
username, password = Base64.urlsafe_decode64(basic_token).split(':')
@current_user ||= ApiUser.find_by(username: username, plain_text_password: password)

return if @current_user

raise(ArgumentError)
rescue NoMethodError, ArgumentError
@response = { code: 2202, message: 'Invalid authorization information' }
render(json: @response, status: :unauthorized)
end

def basic_token
pattern = /^Basic /
header = request.headers['Authorization']
header = header.gsub(pattern, '') if header&.match(pattern)
header.strip
end

def set_values_to_data(login:, registrar:)
data = login.as_json(only: %i[id
username
name
uuid
roles
accreditation_date
accreditation_expire_date])
data[:registrar_name] = registrar.name
data[:registrar_reg_no] = registrar.reg_no
data[:registrar_email] = registrar.email
data[:code] = registrar.code
data
end

def render_success(code: nil, message: nil, data: nil)
@response = { code: code || 1000, message: message || 'Command completed successfully',
data: data || {} }

render(json: @response, status: :ok)
end
end
end
end
end
28 changes: 28 additions & 0 deletions app/controllers/api/v1/accreditation_center/base_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'auth_token/auth_token_decryptor'

module Api
module V1
module AccreditationCenter
class BaseController < ActionController::API
rescue_from ActiveRecord::RecordNotFound, with: :show_not_found_error
rescue_from ActiveRecord::RecordInvalid, with: :show_invalid_record_error
rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
error = {}
error[parameter_missing_exception.param] = ['parameter is required']
response = { errors: [error] }
render json: response, status: :unprocessable_entity
end

private

def show_not_found_error
render json: { errors: [{ base: ['Not found'] }] }, status: :not_found
end

def show_invalid_record_error(exception)
render json: { errors: exception.record.errors }, status: :bad_request
end
end
end
end
end
21 changes: 21 additions & 0 deletions app/controllers/api/v1/accreditation_center/contacts_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'serializers/repp/contact'

module Api
module V1
module AccreditationCenter
class ContactsController < ::Api::V1::AccreditationCenter::BaseController
def show
@contact = Contact.find_by(code: params[:id])

if @contact
render json: { code: 1000, contact: Serializers::Repp::Contact.new(@contact,
show_address: false).to_json },
status: :found
else
render json: { errors: 'Contact not found' }, status: :not_found
end
end
end
end
end
end
21 changes: 21 additions & 0 deletions app/controllers/api/v1/accreditation_center/domains_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'serializers/repp/domain'

module Api
module V1
module AccreditationCenter
class DomainsController < ::Api::V1::AccreditationCenter::BaseController
def show
@domain = Domain.find_by(name: params[:name])

if @domain
render json: { code: 1000, domain: Serializers::Repp::Domain.new(@domain,
sponsored: true).to_json },
status: :found
else
render json: { errors: 'Domain not found' }, status: :not_found
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Api
module V1
module AccreditationCenter
class InvoiceStatusController < ::Api::V1::AccreditationCenter::BaseController
def index
username, password = Base64.urlsafe_decode64(basic_token).split(':')
@current_user ||= ApiUser.find_by(username: username, plain_text_password: password)

return render json: { errors: 'No user found' }, status: :not_found if @current_user.nil?

@invoices = @current_user.registrar.invoices.select { |i| i.cancelled_at != nil }

if @invoices
render json: { code: 1000, invoices: @invoices },
status: :found
else
render json: { errors: 'No invoices' }, status: :not_found
end
end

private

def basic_token
pattern = /^Basic /
header = request.headers['Authorization']
header = header.gsub(pattern, '') if header&.match(pattern)
header.strip
end
end
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/repp/v1/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ def check_ip_restriction
def webclient_request?
return if Rails.env.test?

header = request.headers['AccreditationToken']
return if header == ENV['accreditation_secret']

ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip)
end

Expand All @@ -131,6 +134,10 @@ def validate_webclient_ca

render(json: @response, status: :unauthorized)
end

def logger
Rails.logger
end
end
end
end
4 changes: 2 additions & 2 deletions app/controllers/repp/v1/domains_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def show
param :registrant, String, required: true, desc: 'Registrant contact code'
param :reserved_pw, String, required: false, desc: 'Reserved password for domain'
param :transfer_code, String, required: false, desc: 'Desired transfer code for domain'
param :period, Integer, required: true, desc: 'Registration period in months or years'
# param :period, String, required: true, desc: 'Registration period in months or years'
param :period_unit, String, required: true, desc: 'Period type (month m) or (year y)'
param :nameservers_attributes, Array, required: false, desc: 'Domain nameservers' do
param :hostname, String, required: true, desc: 'Nameserver hostname'
Expand Down Expand Up @@ -64,7 +64,7 @@ def create
handle_errors(@domain) and return unless action.call
# rubocop:enable Style/AndOr

render_success(data: { domain: { name: @domain.name } })
render_success(data: { domain: { name: @domain.name, transfer_code: @domain.transfer_code } })
end

api :PUT, '/repp/v1/domains/:domain_name'
Expand Down
38 changes: 38 additions & 0 deletions app/controllers/repp/v1/registrar/accreditation_info_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Repp
module V1
module Registrar
class AccreditationInfoController < BaseController
api :GET, 'repp/v1/registrar/accreditation/get_info'
desc 'check login user and return data'

def index
login = current_user
registrar = current_user.registrar

# rubocop:disable Style/AndOr
render_success(data: nil) and return unless login
# rubocop:enable Style/AndOr

data = set_values_to_data(login: login, registrar: registrar)

render_success(data: data)
end

private

def set_values_to_data(login:, registrar:)
data = login.as_json(only: %i[id
username
name
uuid
roles
accreditation_date
accreditation_expire_date])
data[:registrar_name] = registrar.name
data[:registrar_reg_no] = registrar.reg_no
data
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module Repp
module V1
module Registrar
class AccreditationResultsController < ActionController::API
before_action :authenticate_shared_key

TEMPORARY_SECRET_KEY = ENV['accreditation_secret'].freeze

api :POST, 'repp/v1/registrar/accreditation/push_results'
desc 'added datetime results'

def create
username = params[:accreditation_result][:username]
result = params[:accreditation_result][:result]

record_accreditation_result(username, result) if result
rescue ActiveRecord::RecordNotFound
record_not_found(username)
end

private

def record_accreditation_result(username, result)
user = ApiUser.find_by(username: username)

raise ActiveRecord::RecordNotFound if user.nil?

user.accreditation_date = DateTime.current

return unless user.save

render_success(data: { user: user,
result: result,
message: 'Accreditation info successfully added' })
end

def authenticate_shared_key
api_key = "Basic #{TEMPORARY_SECRET_KEY}"
render_failed unless api_key == request.authorization
end

def record_not_found(username)
@response = { code: 2303, message: "Object '#{username}' does not exist" }
render(json: @response)
end

def render_failed
@response = { code: 2202, message: 'Invalid authorization information' }
render(json: @response, status: :unauthorized)
end

def render_success(code: nil, message: nil, data: nil)
@response = { code: code || 1000, message: message || 'Command completed successfully',
data: data || {} }

render(json: @response, status: :ok)
end
end
end
end
end
2 changes: 1 addition & 1 deletion app/interactions/actions/domain_create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def assign_domain_auth_codes
end

def assign_domain_period
domain.period = params[:period]
domain.period = params[:period].to_i
domain.period_unit = params[:period_unit]
end

Expand Down
3 changes: 3 additions & 0 deletions config/application.yml.sample
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ sk_digi_doc_service_name: 'Testimine'
registrant_api_base_url:
registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas

# Accreditation Center API
accr_center_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas

# Shared key for REST-WHOIS Bounces API incl. CERT
rwhois_bounces_api_shared_key: testkey

Expand Down
18 changes: 18 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require 'sidekiq/web'

Rails.application.routes.draw do
get 'practice/index'
get 'practice/contact'
# https://github.com/internetee/epp_proxy#translation-of-epp-calls
namespace :epp do
constraints(EppConstraint.new(:session)) do
Expand Down Expand Up @@ -72,6 +74,12 @@
get '/all_notifications', to: 'notifications#all_notifications'
end
end
resource :accreditation, only: [:index] do
collection do
get '/get_info', to: 'accreditation_info#index'
post '/push_results', to: 'accreditation_results#create'
end
end
resources :nameservers do
collection do
put '/', to: 'nameservers#update'
Expand Down Expand Up @@ -118,6 +126,16 @@
resources :companies, only: %i[index]
end

namespace :accreditation_center do
# At the moment invoice_status endpoint returns only cancelled invoices. But in future logic of this enpoint can change.
# And it will need to return invoices of different statuses. I decided to leave the name of the endpoint "invoice_status"
resources :invoice_status, only: [ :index ]
resource :domains, only: [ :show ], param: :name
resource :contacts, only: [ :show ], param: :id
# resource :auth, only: [ :index ]
get 'auth', to: 'auth#index'
end

resources :auctions, only: %i[index show update], param: :uuid
resources :contact_requests, only: %i[create update], param: :id
resources :bounces, only: %i[create]
Expand Down
6 changes: 6 additions & 0 deletions db/migrate/20210729131100_add_field_to_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddFieldToUser < ActiveRecord::Migration[6.1]
def change
add_column :users, :accreditation_date, :datetime
add_column :users, :accreditation_expire_date, :datetime
end
end
5 changes: 5 additions & 0 deletions db/migrate/20210729134625_add_column_to_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddColumnToUser < ActiveRecord::Migration[6.1]
def change
add_column :users, :uuid, :uuid, default: 'gen_random_uuid()'
end
end
Loading