新增:webhook service
This commit is contained in:
parent
d59e99feca
commit
17279c56f4
|
@ -1,42 +1,42 @@
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
#
|
#
|
||||||
# Table name: attachments
|
# Table name: attachments
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# container_id :integer
|
# container_id :integer
|
||||||
# container_type :string(30)
|
# container_type :string(30)
|
||||||
# filename :string(255) default(""), not null
|
# filename :string(255) default(""), not null
|
||||||
# disk_filename :string(255) default(""), not null
|
# disk_filename :string(255) default(""), not null
|
||||||
# filesize :integer default("0"), not null
|
# filesize :integer default("0"), not null
|
||||||
# content_type :string(255) default("")
|
# content_type :string(255) default("")
|
||||||
# digest :string(60) default(""), not null
|
# digest :string(60) default(""), not null
|
||||||
# downloads :integer default("0"), not null
|
# downloads :integer default("0"), not null
|
||||||
# author_id :integer default("0"), not null
|
# author_id :integer default("0"), not null
|
||||||
# created_on :datetime
|
# created_on :datetime
|
||||||
# description :text(65535)
|
# description :text(65535)
|
||||||
# disk_directory :string(255)
|
# disk_directory :string(255)
|
||||||
# attachtype :integer default("1")
|
# attachtype :integer default("1")
|
||||||
# is_public :integer default("1")
|
# is_public :integer default("1")
|
||||||
# copy_from :string(255)
|
# copy_from :string(255)
|
||||||
# quotes :integer default("0")
|
# quotes :integer default("0")
|
||||||
# is_publish :integer default("1")
|
# is_publish :integer default("1")
|
||||||
# publish_time :datetime
|
# publish_time :datetime
|
||||||
# resource_bank_id :integer
|
# resource_bank_id :integer
|
||||||
# unified_setting :boolean default("1")
|
# unified_setting :boolean default("1")
|
||||||
# cloud_url :string(255) default("")
|
# cloud_url :string(255) default("")
|
||||||
# course_second_category_id :integer default("0")
|
# course_second_category_id :integer default("0")
|
||||||
# delay_publish :boolean default("0")
|
# delay_publish :boolean default("0")
|
||||||
# link :string(255)
|
# link :string(255)
|
||||||
# clone_id :integer
|
# clone_id :integer
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
# index_attachments_on_author_id (author_id)
|
# index_attachments_on_author_id (author_id)
|
||||||
# index_attachments_on_clone_id (clone_id)
|
# index_attachments_on_clone_id (clone_id)
|
||||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||||
# index_attachments_on_created_on (created_on)
|
# index_attachments_on_created_on (created_on)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Attachment < ApplicationRecord
|
class Attachment < ApplicationRecord
|
||||||
|
@ -184,4 +184,14 @@ class Attachment < ApplicationRecord
|
||||||
is_pdf
|
is_pdf
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class Gitea::WebhookTask < Gitea::Base
|
class Gitea::WebhookTask < Gitea::Base
|
||||||
serialize :payload_content, JSON
|
serialize :payload_content, JSON
|
||||||
serialize :request_content, JSON
|
serialize :request_content, JSON
|
||||||
|
serialize :response_content, JSON
|
||||||
|
|
||||||
self.inheritance_column = nil
|
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}
|
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
|
end
|
|
@ -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
|
SendTemplateMessageJob.perform_later('IssueExpire', self.id) if Site.has_notice_menu? && self.due_date == Date.today + 1.days
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -32,4 +32,10 @@ class IssuePriority < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_builder
|
||||||
|
Jbuilder.new do |priority|
|
||||||
|
priority.(self, :id, :name)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,4 +44,10 @@ class IssueStatus < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_builder
|
||||||
|
Jbuilder.new do |status|
|
||||||
|
status.(self, :id, :name)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,4 +53,11 @@ class IssueTag < ApplicationRecord
|
||||||
self.update_column(:pull_requests_count, pull_request_issues.size)
|
self.update_column(:pull_requests_count, pull_request_issues.size)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def to_builder
|
||||||
|
Jbuilder.new do |tag|
|
||||||
|
tag.(self, :id, :name, :description)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -446,4 +446,59 @@ class Project < ApplicationRecord
|
||||||
def del_project_issue_cache_delete_count
|
def del_project_issue_cache_delete_count
|
||||||
$redis_cache.hdel("issue_cache_delete_count", self.id)
|
$redis_cache.hdel("issue_cache_delete_count", self.id)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -859,6 +859,16 @@ class User < Owner
|
||||||
end
|
end
|
||||||
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
|
protected
|
||||||
def validate_password_length
|
def validate_password_length
|
||||||
# 管理员的初始密码是5位
|
# 管理员的初始密码是5位
|
||||||
|
|
|
@ -55,6 +55,12 @@ class Version < ApplicationRecord
|
||||||
User.select(:login, :lastname,:firstname, :nickname)&.find_by_id(self.user_id)
|
User.select(:login, :lastname,:firstname, :nickname)&.find_by_id(self.user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_builder
|
||||||
|
Jbuilder.new do |version|
|
||||||
|
version.(self, :id, :name, :description, :effective_date)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def send_create_message_to_notice_system
|
def send_create_message_to_notice_system
|
||||||
SendTemplateMessageJob.perform_later('ProjectMilestone', self.id, self.user_id) if Site.has_notice_menu?
|
SendTemplateMessageJob.perform_later('ProjectMilestone', self.id, self.user_id) if Site.has_notice_menu?
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue