5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-24 15:56:20 +00:00
panel/app/controllers/api/v1/webhooks_controller.rb

78 lines
2.4 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
module Api
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)
#
# @return [nil]
2023-08-16 19:21:48 +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
GitPullJob.perform_later(site, usuarie, message)
head :ok
end
2023-08-14 19:49:24 +00:00
2023-08-16 19:21:48 +00:00
private
# encuentra el sitio a partir de la url
2023-08-16 19:21:48 +00:00
def site
@site ||= Site.find_by_name!(params[:site_id])
end
# valida el token que envía la plataforma del webhook
#
# @return [String]
2023-08-16 19:21:48 +00:00
def token
@token ||=
begin
# Gitlab
2023-08-16 19:26:39 +00:00
if request.headers['X-Gitlab-Token'].present?
request.headers['X-Gitlab-Token']
# Github
2023-08-16 19:26:39 +00:00
elsif request.headers['X-Hub-Signature-256'].present?
2023-08-16 19:46:11 +00:00
token_from_signature(request.headers['X-Hub-Signature-256'], 'sha256=')
# Gitea
2023-08-16 19:46:11 +00:00
elsif request.headers['X-Gitea-Signature'].present?
token_from_signature(request.headers['X-Gitea-Signature'])
else
raise ActiveRecord::RecordNotFound, 'proveedor no soportado'
end
2023-08-16 19:21:48 +00:00
end
end
# valida token a partir de firma de webhook
#
# @return [String, Boolean]
2023-08-16 19:24:33 +00:00
def token_from_signature(signature, prepend = '')
2023-08-16 19:21:48 +00:00
payload = request.body.read
site.roles.where(temporal: false, rol: 'usuarie').pluck(:token).find do |token|
new_signature = prepend + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), token, payload)
ActiveSupport::SecurityUtils.secure_compare(new_signature, signature.to_s)
end.tap do |t|
raise ActiveRecord::RecordNotFound, 'token no encontrado' if t.nil?
end
end
2023-08-16 19:21:48 +00:00
# encuentra le usuarie
def usuarie
@usuarie ||= site.roles.find_by!(temporal: false, rol: 'usuarie', token: token).usuarie
2023-08-16 19:21:48 +00:00
end
# respuesta de error a plataformas
def platforms_answer(exception)
ExceptionNotifier.notify_exception(exception, data: { headers: request.headers.to_h }
2023-08-16 19:23:39 +00:00
head :forbidden
end
end
end
2023-08-16 19:21:48 +00:00
end