2023-07-26 17:44:11 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Api
|
2023-08-15 19:59:16 +00:00
|
|
|
module V1
|
|
|
|
# Recibe webhooks y lanza un PullJob
|
|
|
|
class WebhooksController < BaseController
|
|
|
|
# responde con forbidden si falla la validación del token
|
|
|
|
rescue_from ActiveRecord::RecordNotFound, with: :platforms_answer
|
|
|
|
|
|
|
|
# Trae los cambios a partir de un post de Webhooks:
|
|
|
|
# (Gitlab, Github, Gitea, etc)
|
2023-08-15 22:25:06 +00:00
|
|
|
#
|
|
|
|
# @return [nil]
|
2023-08-15 19:59:16 +00:00
|
|
|
def pull
|
|
|
|
message = I18n.with_locale(site.default_locale) do
|
|
|
|
I18n.t('webhooks.pull.message')
|
2023-08-14 19:49:24 +00:00
|
|
|
end
|
|
|
|
|
2023-08-15 19:59:16 +00:00
|
|
|
GitPullJob.perform_later(site, usuarie, message)
|
|
|
|
head :ok
|
|
|
|
end
|
2023-08-14 19:49:24 +00:00
|
|
|
|
2023-08-15 19:59:16 +00:00
|
|
|
private
|
2023-08-10 19:05:14 +00:00
|
|
|
|
2023-08-15 19:59:16 +00:00
|
|
|
# encuentra el sitio a partir de la url
|
|
|
|
def site
|
|
|
|
@site ||= Site.find_by_name!(params[:site_id])
|
|
|
|
end
|
2023-08-14 15:50:18 +00:00
|
|
|
|
2023-08-15 19:59:16 +00:00
|
|
|
# valida el token que envía la plataforma del webhook
|
|
|
|
#
|
|
|
|
# @return [String]
|
|
|
|
def token
|
|
|
|
@token ||=
|
|
|
|
begin
|
|
|
|
# Gitlab
|
|
|
|
if request.headers['X-Gitlab-Token']
|
|
|
|
request.headers['X-Gitlab-Token']
|
|
|
|
# Github
|
|
|
|
elsif request.headers['X-HUB-SIGNATURE-256']
|
2023-08-15 22:25:06 +00:00
|
|
|
token_from_signature(request.env['HTTP_X_HUB_SIGNATURE_256'])
|
2023-08-15 19:59:16 +00:00
|
|
|
# Gitea
|
2023-08-16 17:57:01 +00:00
|
|
|
elsif request.headers['HTTP_X_GITEA_SIGNATURE']
|
2023-08-16 15:58:14 +00:00
|
|
|
token_from_signature(request.env['HTTP_X_GITEA_SIGNATURE'])
|
2023-08-15 19:59:16 +00:00
|
|
|
else
|
2023-08-16 15:58:14 +00:00
|
|
|
raise ActiveRecord::RecordNotFound
|
2023-08-15 19:59:16 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# valida token a partir de firma de webhook
|
|
|
|
#
|
2023-08-15 22:25:06 +00:00
|
|
|
# @return [String, Boolean]
|
2023-08-15 19:59:16 +00:00
|
|
|
def token_from_signature(signature)
|
|
|
|
payload = request.body.read
|
|
|
|
site.roles.where(temporal: false, rol: 'usuarie').pluck(:token).find do |token|
|
|
|
|
new_signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), token, payload)
|
|
|
|
ActiveSupport::SecurityUtils.secure_compare(new_signature, signature)
|
2023-08-15 22:25:06 +00:00
|
|
|
end.tap do |t|
|
2023-08-16 16:39:29 +00:00
|
|
|
raise ActiveRecord::RecordNotFound, 'token no encontrado' if t.nil?
|
2023-08-14 15:50:18 +00:00
|
|
|
end
|
2023-08-15 19:59:16 +00:00
|
|
|
end
|
2023-08-14 15:50:18 +00:00
|
|
|
|
2023-08-15 19:59:16 +00:00
|
|
|
# encuentra le usuarie
|
|
|
|
def usuarie
|
|
|
|
@usuarie ||= site.roles.find_by!(temporal: false, rol: 'usuarie', token: token).usuarie
|
|
|
|
end
|
2023-08-10 19:05:14 +00:00
|
|
|
|
2023-08-15 19:59:16 +00:00
|
|
|
# respuesta de error a plataformas
|
2023-08-16 16:39:29 +00:00
|
|
|
def platforms_answer(exception)
|
2023-08-15 19:59:16 +00:00
|
|
|
head :forbidden
|
2023-08-16 16:39:29 +00:00
|
|
|
ExceptionNotifier.notify_exception(exception, data: { params: params.to_h })
|
2023-07-26 17:44:11 +00:00
|
|
|
end
|
2023-08-15 19:59:16 +00:00
|
|
|
end
|
2023-07-26 17:44:11 +00:00
|
|
|
end
|