Skip to content

Commit

Permalink
Added endpoints for creating and downloading api user certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergei Tsoganov authored and Sergei Tsoganov committed Jun 28, 2023
1 parent b558c80 commit 47b6a1b
Show file tree
Hide file tree
Showing 18 changed files with 368 additions and 93 deletions.
30 changes: 20 additions & 10 deletions app/controllers/admin/certificates_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
module Admin
class CertificatesController < BaseController
load_and_authorize_resource
before_action :set_certificate, :set_api_user, only: [:sign, :show, :download_csr, :download_crt, :revoke, :destroy]
before_action :set_certificate, :set_api_user, only: %i[sign show download_csr download_crt revoke destroy]

def show;
end
def show; end

def new
@api_user = ApiUser.find(params[:api_user_id])
Expand All @@ -28,11 +27,9 @@ def create
end

def destroy
if @certificate.interface == Certificate::REGISTRAR
@certificate.revoke!
end
success = @certificate.revokable? ? revoke_and_destroy_certificate : @certificate.destroy

if @certificate.destroy
if success
flash[:notice] = I18n.t('record_deleted')
redirect_to admin_registrar_api_user_path(@api_user.registrar, @api_user)
else
Expand All @@ -42,8 +39,9 @@ def destroy
end

def sign
if @certificate.sign!
if @certificate.sign!(password: certificate_params[:password])
flash[:notice] = I18n.t('record_updated')
notify_api_user
redirect_to [:admin, @api_user, @certificate]
else
flash.now[:alert] = I18n.t('failed_to_update_record')
Expand All @@ -52,7 +50,7 @@ def sign
end

def revoke
if @certificate.revoke!
if @certificate.revoke!(password: certificate_params[:password])
flash[:notice] = I18n.t('record_updated')
else
flash[:alert] = I18n.t('failed_to_update_record')
Expand Down Expand Up @@ -84,10 +82,22 @@ def set_api_user

def certificate_params
if params[:certificate]
params.require(:certificate).permit(:crt, :csr)
params.require(:certificate).permit(:crt, :csr, :password)
else
{}
end
end

def notify_api_user
api_user_email = @api_user.registrar.email

CertificateMailer.signed(email: api_user_email, api_user: @api_user,
crt: OpenSSL::X509::Certificate.new(@certificate.crt))
.deliver_now
end

def revoke_and_destroy_certificate
@certificate.revoke!(password: certificate_params[:password]) && @certificate.destroy
end
end
end
5 changes: 5 additions & 0 deletions app/controllers/repp/v1/api_users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module Repp
module V1
class ApiUsersController < BaseController
before_action :find_api_user, only: %i[show update destroy]
load_and_authorize_resource

THROTTLED_ACTIONS = %i[index show create update destroy].freeze
Expand Down Expand Up @@ -60,6 +61,10 @@ def destroy

private

def find_api_user
@api_user = current_user.registrar.api_users.find(params[:id])
end

def api_user_params
params.require(:api_user).permit(:username, :plain_text_password, :active,
:identity_code, { roles: [] })
Expand Down
41 changes: 32 additions & 9 deletions app/controllers/repp/v1/certificates_controller.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1,52 @@
require 'serializers/repp/certificate'
module Repp
module V1
class CertificatesController < BaseController
THROTTLED_ACTIONS = %i[create].freeze
before_action :find_certificate, only: %i[show download]
load_and_authorize_resource param_method: :cert_params

THROTTLED_ACTIONS = %i[show create download].freeze
include Shunter::Integration::Throttle

api :GET, '/repp/v1/api_users/:api_user_id/certificates/:id'
desc "Get a specific api user's specific certificate data"
def show
serializer = Serializers::Repp::Certificate.new(@certificate)
render_success(data: { cert: serializer.to_json })
end

api :POST, '/repp/v1/certificates'
desc 'Submit a new api user certificate signing request'
def create
authorize! :create, Certificate
@api_user = current_user.registrar.api_users.find(cert_params[:api_user_id])

csr = decode_cert_params(cert_params[:csr])

@certificate = @api_user.certificates.build(csr: csr)
unless @certificate.save

if @certificate.save
notify_admins
render_success(data: { api_user: { id: @api_user.id } })
else
handle_non_epp_errors(@certificate)
return
end
end

notify_admins
render_success(data: { api_user: { id: @api_user.id } })
api :get, '/repp/v1/api_users/:api_user_id/certificates/:id/download'
desc "Download a specific api user's specific certificate"
param :type, String, required: true, desc: 'Type of certificate (csr or crt)'
def download
filename = "#{@api_user.username}_#{Time.zone.today.strftime('%y%m%d')}_portal.#{params[:type]}.pem"
send_data @certificate[params[:type].to_s], filename: filename
end

private

def find_certificate
@api_user = current_user.registrar.api_users.find(params[:api_user_id])
@certificate = @api_user.certificates.find(params[:id])
end

def cert_params
params.require(:certificate).permit(:api_user_id, csr: %i[body type])
end
Expand All @@ -40,9 +63,9 @@ def notify_admins
return if admin_users_emails.empty?

admin_users_emails.each do |email|
CertificateMailer.new_certificate_signing_request(email: email,
api_user: @api_user,
csr: @certificate)
CertificateMailer.certificate_signing_requested(email: email,
api_user: @api_user,
csr: @certificate)
.deliver_now
end
end
Expand Down
7 changes: 5 additions & 2 deletions app/controllers/repp/v1/invoices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module Repp
module V1
class InvoicesController < BaseController # rubocop:disable Metrics/ClassLength
before_action :find_invoice, only: %i[show download send_to_recipient cancel]
load_and_authorize_resource

THROTTLED_ACTIONS = %i[download add_credit send_to_recipient cancel index show].freeze
Expand Down Expand Up @@ -35,8 +36,6 @@ def show
desc 'Download a specific invoice as pdf file'
def download
filename = "Invoice-#{@invoice.number}.pdf"
@response = { code: 1000, message: 'Command completed successfully',
data: filename }
send_data @invoice.as_pdf, filename: filename
end

Expand Down Expand Up @@ -91,6 +90,10 @@ def add_credit

private

def find_invoice
@invoice = current_user.registrar.invoices.find(params[:id])
end

def index_params
params.permit(:id, :limit, :offset, :details, :q, :simple,
:page, :per_page,
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/repp/v1/white_ips_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Repp
module V1
class WhiteIpsController < BaseController
before_action :find_white_ip, only: %i[show update destroy]
load_and_authorize_resource

THROTTLED_ACTIONS = %i[index show create update destroy].freeze
Expand Down Expand Up @@ -57,6 +58,10 @@ def destroy

private

def find_white_ip
@white_ip = current_user.registrar.white_ips.find(params[:id])
end

def white_ip_params
params.require(:white_ip).permit(:ipv4, :ipv6, interfaces: [])
end
Expand Down
9 changes: 8 additions & 1 deletion app/mailers/certificate_mailer.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
class CertificateMailer < ApplicationMailer
def new_certificate_signing_request(email:, api_user:, csr:)
def certificate_signing_requested(email:, api_user:, csr:)
@certificate = csr
@api_user = api_user
subject = 'New Certificate Signing Request Received'
mail(to: email, subject: subject)
end

def signed(email:, api_user:, crt:)
@crt = crt
@api_user = api_user
subject = "Certificate Signing Confirmation for API User '#{@api_user.username}'"
mail(to: email, subject: subject)
end
end
2 changes: 1 addition & 1 deletion app/models/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def super # Registrar/api_user dynamic role
billing
can :manage, ApiUser
can :manage, WhiteIp
can :create, Certificate
can :manage, Certificate
end

def epp # Registrar/api_user dynamic role
Expand Down
Loading

0 comments on commit 47b6a1b

Please sign in to comment.