5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-29 18:26:22 +00:00

Merge branch 'issue-13903' of https://0xacab.org/sutty/sutty into 17.3.alpine.panel.sutty.nl

This commit is contained in:
Sutty 2023-08-16 18:09:20 +00:00
commit c9337a0ad5
6 changed files with 94 additions and 20 deletions

View file

@ -1,22 +1,75 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V1 module V1
# Recibe webhooks y lanza jobs # Recibe webhooks y lanza un PullJob
class WebhooksController < BaseController class WebhooksController < BaseController
# Trae los cambios a partir de un post de Webhooks: # responde con forbidden si falla la validación del token
# (Gitlab, Github, Guitea, etc) rescue_from ActiveRecord::RecordNotFound, with: :platforms_answer
def pull
site = Site.find_by_name!(params[:site_id])
usuarie = GitAuthor.new email: "webhook@#{Site.domain}", name: 'Webhook'
message = I18n.with_locale(site.default_locale) do
I18n.t('webhooks.pull.message')
end
GitPullJob.perform_later(site, usuarie, message) # Trae los cambios a partir de un post de Webhooks:
# (Gitlab, Github, Gitea, etc)
head :ok #
# @return [nil]
def pull
message = I18n.with_locale(site.default_locale) do
I18n.t('webhooks.pull.message')
end
GitPullJob.perform_later(site, usuarie, message)
head :ok
end
private
# encuentra el sitio a partir de la url
def site
@site ||= Site.find_by_name!(params[:site_id])
end
# 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']
token_from_signature(request.env['HTTP_X_HUB_SIGNATURE_256'])
# Gitea
elsif request.headers['HTTP_X_GITEA_SIGNATURE']
token_from_signature(request.env['HTTP_X_GITEA_SIGNATURE'])
else
raise ActiveRecord::RecordNotFound
end
end
end
# valida token a partir de firma de webhook
#
# @return [String, Boolean]
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)
end.tap do |t|
raise ActiveRecord::RecordNotFound, 'token no encontrado' if t.nil?
end end
end end
# encuentra le usuarie
def usuarie
@usuarie ||= site.roles.find_by!(temporal: false, rol: 'usuarie', token: token).usuarie
end
# respuesta de error a plataformas
def platforms_answer(exception)
head :forbidden
ExceptionNotifier.notify_exception(exception, data: { params: params.to_h })
end end
end
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
# Permite traer los cambios cada vez que se # Permite traer los cambios desde webhooks
# hace un push al repositorio
class GitPullJob < ApplicationJob class GitPullJob < ApplicationJob
# @param :site [Site] # @param :site [Site]
# @param :usuarie [Usuarie] # @param :usuarie [Usuarie]

View file

@ -14,6 +14,8 @@ class Rol < ApplicationRecord
validates_inclusion_of :rol, in: ROLES validates_inclusion_of :rol, in: ROLES
before_save :add_token_if_missing!
def invitade? def invitade?
rol == INVITADE rol == INVITADE
end end
@ -25,4 +27,11 @@ class Rol < ApplicationRecord
def self.role?(rol) def self.role?(rol)
ROLES.include? rol ROLES.include? rol
end end
private
# Asegurarse que tenga un token
def add_token_if_missing!
self.token ||= SecureRandom.hex(64)
end
end end

View file

@ -45,9 +45,7 @@ class Site
# @return [Integer] # @return [Integer]
def fetch def fetch
if origin.check_connection(:fetch, credentials: credentials) if origin.check_connection(:fetch, credentials: credentials)
rugged.fetch(origin, credentials: credentials)[:received_objects].tap do |objects| rugged.fetch(origin, credentials: credentials)[:received_objects]
git_sh("git", "lfs", "fetch", "origin", default_branch) if objects&.positive?
end
else else
0 0
end end
@ -77,6 +75,8 @@ class Site
# Forzamos el checkout para mover el HEAD al último commit y # Forzamos el checkout para mover el HEAD al último commit y
# escribir los cambios # escribir los cambios
rugged.checkout 'HEAD', strategy: :force rugged.checkout 'HEAD', strategy: :force
git_sh("git", "lfs", "fetch", "origin", default_branch)
# reemplaza los pointers por los archivos correspondientes # reemplaza los pointers por los archivos correspondientes
git_sh("git", "lfs", "checkout") git_sh("git", "lfs", "checkout")
commit commit

View file

@ -479,7 +479,7 @@ es:
message: 'Actualización del esqueleto' message: 'Actualización del esqueleto'
webhooks_controller: webhooks_controller:
pull: pull:
message: 'Pull de webhooks' message: 'Traer los cambios a partir de un evento remoto'
footer: footer:
powered_by: 'es desarrollada por' powered_by: 'es desarrollada por'
i18n: i18n:

View file

@ -0,0 +1,12 @@
class AddTokenToRoles < ActiveRecord::Migration[6.1]
def up
add_column :roles, :token, :string
Rol.find_each do |m|
m.update_column( :token, SecureRandom.hex(64) )
end
end
def down
remove_column :roles, :token
end
end