新增:webhook service

This commit is contained in:
yystopf 2023-03-29 18:49:20 +08:00
parent d59e99feca
commit 17279c56f4
11 changed files with 311 additions and 44 deletions

View File

@ -1,42 +1,42 @@
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :string(255)
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
# link :string(255)
# clone_id :integer
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_clone_id (clone_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_created_on (created_on)
#
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :string(255)
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
# link :string(255)
# clone_id :integer
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_clone_id (clone_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_created_on (created_on)
#
class Attachment < ApplicationRecord
@ -184,4 +184,14 @@ class Attachment < ApplicationRecord
is_pdf
end
def to_builder
Jbuilder.new do |attachment|
attachment.id self.id
attachment.title self.title
attachment.filesize self.filesize
attachment.is_pdf self.is_pdf?
attachment.created_on self.created_on.strftime("%Y-%m-%d %H:%M")
attachment.content_type self.content_type
end
end
end

View File

@ -1,6 +1,7 @@
class Gitea::WebhookTask < Gitea::Base
serialize :payload_content, JSON
serialize :request_content, JSON
serialize :response_content, JSON
self.inheritance_column = nil
@ -10,9 +11,4 @@ class Gitea::WebhookTask < Gitea::Base
enum type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9}
def response_content_json
JSON.parse(response_content)
rescue
{}
end
end

View File

@ -217,4 +217,30 @@ class Issue < ApplicationRecord
SendTemplateMessageJob.perform_later('IssueExpire', self.id) if Site.has_notice_menu? && self.due_date == Date.today + 1.days
end
def to_builder
Jbuilder.new do |issue|
issue.(self, :id, :project_issues_index, :subject, :description)
issue.created_at self.created_on.strftime("%Y-%m-%d %H:%M")
issue.updated_at self.updated_on.strftime("%Y-%m-%d %H:%M")
issue.tags self.show_issue_tags.map{|t| t.to_builder}
issue.status self.issue_status.to_builder
if self.priority.present?
issue.priority self.priority.to_builder
else
issue.priority nil
end
if self.version.present?
issue.milestone self.version.to_builder
else
issue.milestone nil
end
issue.author self.user.to_builder
issue.assigners self.show_assigners.map{|t| t.to_builder}
issue.participants self.participants.distinct.map{|t| t.to_builder}
issue.comment_journals_count self.comment_journals.size
issue.operate_journals_count self.operate_journals.size
issue.attachments self.attachments.map{|t| t.to_builder}
end
end
end

View File

@ -32,4 +32,10 @@ class IssuePriority < ApplicationRecord
end
end
end
def to_builder
Jbuilder.new do |priority|
priority.(self, :id, :name)
end
end
end

View File

@ -44,4 +44,10 @@ class IssueStatus < ApplicationRecord
end
end
end
def to_builder
Jbuilder.new do |status|
status.(self, :id, :name)
end
end
end

View File

@ -53,4 +53,11 @@ class IssueTag < ApplicationRecord
self.update_column(:pull_requests_count, pull_request_issues.size)
end
def to_builder
Jbuilder.new do |tag|
tag.(self, :id, :name, :description)
end
end
end

View File

@ -446,4 +446,59 @@ class Project < ApplicationRecord
def del_project_issue_cache_delete_count
$redis_cache.hdel("issue_cache_delete_count", self.id)
end
def to_builder
Jbuilder.new do |project|
project.id self.id
project.identifier self.identifier
project.name self.name
project.description Nokogiri::HTML(self.description).text
project.visits self.visits
project.praises_count self.praises_count.to_i
project.watchers_count self.watchers_count.to_i
project.issues_count self.issues_count.to_i
project.pull_requests_count self.pull_requests_count.to_i
project.forked_count self.forked_count.to_i
project.is_public self.is_public
project.mirror_url self.repository&.mirror_url
project.type self&.project_type
project.created_at self.created_on.strftime("%Y-%m-%d %H:%M")
project.updated_at self.updated_on.strftime("%Y-%m-%d %H:%M")
project.forked_from_project_id self.forked_from_project_id
project.platform self.platform
project.author do
if self.educoder?
project_educoder = self.project_educoder
project.name project_educoder&.owner
project.type 'Educoder'
project.login project_educoder&.repo_name.split('/')[0]
project.image_url render_educoder_avatar_url(self.project_educoder)
else
user = self.owner
project.name user.try(:show_real_name)
project.type user&.type
project.login user.login
project.image_url user.get_letter_avatar_url
end
end
project.category do
if self.project_category.blank?
project.nil!
else
project.id self.project_category.id
project.name self.project_category.name
end
end
project.language do
if self.project_language.blank?
project.nil!
else
project.id self.project_language.id
project.name self.project_language.name
end
end
end
end
end

View File

@ -859,6 +859,16 @@ class User < Owner
end
end
def to_builder
Jbuilder.new do |user|
user.(self, :id, :login)
user.name self.real_name
user.email self.mail
user.image_url self.get_letter_avatar_url
end
end
protected
def validate_password_length
# 管理员的初始密码是5位

View File

@ -55,6 +55,12 @@ class Version < ApplicationRecord
User.select(:login, :lastname,:firstname, :nickname)&.find_by_id(self.user_id)
end
def to_builder
Jbuilder.new do |version|
version.(self, :id, :name, :description, :effective_date)
end
end
private
def send_create_message_to_notice_system
SendTemplateMessageJob.perform_later('ProjectMilestone', self.id, self.user_id) if Site.has_notice_menu?

View File

@ -0,0 +1,92 @@
module Webhook::Client
# uuid SecureRandom.uuid
# hmac = OpenSSL::HMAC.new(secret, OpenSSL::Digest::SHA1.new)
# message = Gitea::WebhookTask.last.read_attribute_before_type_cast("payload_content")
# hmac.update(message)
# sha1 = hmac.digest.unpack('H*').first
attr_reader :uuid, :event, :http_method, :content_type, :url, :secret, :payload_content
attr_accessor :request_content, :response_content
def initialize(opts)
@uuid = opts[:uuid]
@event = opts[:event]
@http_method = opts[:http_method]
@content_type = opts[:content_type]
@url = opts[:url]
@secret = opts[:secret]
@payload_content = opts[:payload_content]
@request_content = {}
@response_content = {}
end
def do_request
headers = {}
headers['Content-Type'] = trans_content_type
headers["X-Gitea-Delivery"] = @uuid
headers["X-Gitea-Event"] = @event
headers["X-Gitea-Event-Type"] = @event
headers["X-Gitea-Signature"] = signatureSHA256
headers["X-Gogs-Delivery"] = @uuid
headers["X-Gogs-Event"] = @event
headers["X-Gogs-Event-Type"] = @event
headers["X-Gogs-Signature"] = signatureSHA256
headers["X-Hub-Signature"] = "sha1=" + signatureSHA1
headers["X-Hub-Signature-256"] = "sha256=" + signatureSHA256
headers["X-GitHub-Delivery"] = @uuid
headers["X-GitHub-Event"] = @event
headers["X-GitHub-Event-Type"] = @event
@request_content["url"] = @url
@request_content["http_method"] = @http_method
@request_content["headers"] = headers
response = RestClient::Request.execute(method: trans_http_method, url: @url, headers: headers, payload: payload_content) {|response, request, result| response }
@response_content["status"] = response.code
@response_content["headers"] = response.headers
@response_content["body"] = response.body.to_json
return @request_content, @response_content
end
def request_content
@request_content
end
def response_content
@response_content
end
private
def signatureSHA1
hmac = OpenSSL::HMAC.new(@secret, OpenSSL::Digest::SHA1.new)
message = @payload_content
hmac.digest.unpack('H*').first
end
def signatureSHA256
hmac = OpenSSL::HMAC.new(@secret, OpenSSL::Digest::SHA256.new)
message = @payload_content
hmac.digest.unpack('H*').first
end
def trans_content_type
if @content_type == "form"
return "application/x-www-form-urlencoded"
else
return "application/json"
end
end
def trans_http_method
if @http_method == "GET"
return :get
else
return :post
end
end
end

View File

@ -0,0 +1,53 @@
class Webhook::IssueCreateClient
include Webhook::Client
attr_accessor :webhook, :issue, :sender
attr_accessor :webhook_task
def initialize(webhook, issue, sender)
@webhook = webhook
@issue = issue
@sender = sender
# 创建webhook task
@webhook_task = Gitea::WebhookTask.create(
hook_id: @webhook.id,
uuid: SecureRandom.uuid,
payload_content: payload_content,
event_type: "issues",
is_delivered: true
)
# 构建client参数
super({
uuid: @webhook_task.uuid,
event: "issues",
http_method: @webhook.http_method,
content_type: @webhook.content_type,
url: @webhook.url,
secret: @webhook.secret,
payload_content: @webhook_task.read_attribute_before_type_cast("payload_content")
})
end
def do_request
request_content, response_content = super
@webhook_task.update_attributes({
delivered: Time.now.to_i * 1000000000,
is_succeed: response_content["status"] < 300,
request_content: request_content,
response_content: response_content
})
end
def payload_content
{
"action": "opened",
"number": @issue.project_issues_index,
"issue": JSON.parse(@issue.to_builder.target!),
"project": JSON.parse(@issue.project.to_builder.target!),
"sender": JSON.parse(@sender.to_builder.target!)
}
end
end