| @@ -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 | 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 | |||||