Merge remote-tracking branch 'origin/standalone_develop' into standalone_develop

This commit is contained in:
xxq250 2023-03-14 15:23:42 +08:00
commit 8a35c8ac6e
40 changed files with 640 additions and 85 deletions

View File

@ -10,7 +10,7 @@ class Api::V1::IssuesController < Api::V1::BaseController
@opened_issues_count = @object_result[:opened_issues_count]
@closed_issues_count = @object_result[:closed_issues_count]
if params[:only_name].present?
@issues = kaminary_select_paginate(@object_result[:data].pluck(:id, :subject))
@issues = kaminary_select_paginate(@object_result[:data])
else
@issues = kaminari_paginate(@object_result[:data])
end
@ -86,6 +86,7 @@ class Api::V1::IssuesController < Api::V1::BaseController
def query_params
params.permit(
:only_name,
:category,
:participant_category,
:keyword, :author_id,
@ -99,7 +100,7 @@ class Api::V1::IssuesController < Api::V1::BaseController
params.permit(
:status_id, :priority_id, :milestone_id,
:branch_name, :start_date, :due_date,
:subject, :description,
:subject, :description, :blockchain_token_num,
:issue_tag_ids => [],
:assigner_ids => [],
:attachment_ids => [],

View File

@ -880,9 +880,9 @@ class ApplicationController < ActionController::Base
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise Error, resp_body['message']
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
raise ApplicationService::Error, "区块链接口请求失败."
end
elsif activity_type == "issue_comment_create"
@ -951,9 +951,9 @@ class ApplicationController < ActionController::Base
# 调用区块链接口
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise Error, resp_body['message']
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
raise ApplicationService::Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_create"
# 调用区块链接口
@ -989,9 +989,9 @@ class ApplicationController < ActionController::Base
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'])
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'], current_user&.gitea_token)
if commits.nil?
raise Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
raise ApplicationService::Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
@ -1018,9 +1018,9 @@ class ApplicationController < ActionController::Base
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
raise ApplicationService::Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_merge"
# 调用区块链接口
@ -1043,9 +1043,9 @@ class ApplicationController < ActionController::Base
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'])
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'], current_user&.gitea_token)
if commits.nil?
raise Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
raise ApplicationService::Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
@ -1074,9 +1074,9 @@ class ApplicationController < ActionController::Base
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
raise ApplicationService::Error, "区块链接口请求失败."
end
@ -1099,9 +1099,9 @@ class ApplicationController < ActionController::Base
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 7
raise Error, resp_body['message']
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
raise ApplicationService::Error, "区块链接口请求失败."
end
end
@ -1145,9 +1145,9 @@ class ApplicationController < ActionController::Base
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
raise ApplicationService::Error, "区块链接口请求失败."
end
end
end

View File

@ -160,14 +160,16 @@ class IssuesController < ApplicationController
# 新增时向grimoirelab推送事件
IssueWebhookJob.set(wait: 5.seconds).perform_later(@issue.id)
# author: zxh
# 扣除发起人的token
if @issue.blockchain_token_num > 0
Blockchain::CreateIssue.call(user_id: @issue.author_id, project_id: @issue.project_id, token_num: @issue.blockchain_token_num)
end
if Site.has_blockchain? && @project.use_blockchain
# author: zxh
# 扣除发起人的token
if @issue.blockchain_token_num > 0
Blockchain::CreateIssue.call(user_id: @issue.author_id, project_id: @issue.project_id, token_num: @issue.blockchain_token_num)
end
# 调用上链API存证
push_activity_2_blockchain("issue_create", @issue)
# 调用上链API存证
push_activity_2_blockchain("issue_create", @issue)
end
render json: {status: 0, message: "创建成功", id: @issue.id}
else

View File

@ -50,7 +50,7 @@ class JournalsController < ApplicationController
# author: zxh
# 调用上链API
push_activity_2_blockchain("issue_comment_create", journal)
push_activity_2_blockchain("issue_comment_create", journal) if Site.has_blockchain? && @project.use_blockchain
render :json => { status: 0, message: "评论成功", id: journal.id}
else

View File

@ -77,7 +77,7 @@ class PullRequestsController < ApplicationController
# author: zxh
# 调用上链API
push_activity_2_blockchain("pull_request_create", @pull_request)
push_activity_2_blockchain("pull_request_create", @pull_request) if Site.has_blockchain? && @project.use_blockchain
else
render_error("create pull request error: #{@gitea_pull_request[:status]}")
@ -127,6 +127,18 @@ class PullRequestsController < ApplicationController
return normal_status(-1, "请输入正确的标记。")
end
end
if params[:attached_issue_ids].present?
if params[:attached_issue_ids].is_a?(Array) && params[:attached_issue_ids].size > 1
return normal_status(-1, "最多只能关联一个疑修。")
elsif params[:attached_issue_ids].is_a?(Array) && params[:attached_issue_ids].size == 1
@pull_request&.pull_attached_issues&.destroy_all
params[:attached_issue_ids].each do |issue|
PullAttachedIssue.create!(issue_id: issue, pull_request_id: @pull_request.id)
end
else
return normal_status(-1, "请输入正确的疑修。")
end
end
if params[:status_id].to_i == 5
@issue.issue_times.update_all(end_time: Time.now)
end
@ -157,7 +169,7 @@ class PullRequestsController < ApplicationController
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
# author: zxh
# 调用上链API
push_activity_2_blockchain("pull_request_refuse", @pull_request)
push_activity_2_blockchain("pull_request_refuse", @pull_request) if Site.has_blockchain? && @project.use_blockchain
if colsed === true
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
@ -211,38 +223,23 @@ class PullRequestsController < ApplicationController
# author: zxh
# 调用上链API
push_activity_2_blockchain("pull_request_merge", @pull_request)
push_activity_2_blockchain("pull_request_merge", @pull_request) if Site.has_blockchain? && @project.use_blockchain
# 查看是否fix了相关issue如果fix就转账
if params["fix_issue_id"].nil? || params["fix_issue_id"] == ""
else
issue = Issue.find_by(id: params["fix_issue_id"])
if issue.nil?
normal_status(-1, "关联issue失败")
raise ActiveRecord::Rollback
else
token_num = issue.blockchain_token_num
token_num = token_num.nil? ? 0 : token_num
owner = User.find_by(login: params["owner"])
pr = PullRequest.find_by(id: params["pull_request"]["id"])
if owner.nil? || pr.nil?
normal_status(-1, "关联issue失败")
raise ActiveRecord::Rollback
else
project = Project.find_by(user_id: owner.id, identifier: params["project_id"])
if project.nil?
normal_status(-1, "关联issue失败")
raise ActiveRecord::Rollback
else
author_id = pr.user_id
if token_num > 0
Blockchain::FixIssue.call({user_id: author_id.to_s, project_id: project.id.to_s, token_num: token_num})
end
# update issue to state 5
issue.update(status_id: 5)
end
end
@pull_request.attached_issues.each do |issue|
next if PullAttachedIssue.exists?(issue_id: issue.id, fixed: true)
token_num = issue.blockchain_token_num
token_num = token_num.nil? ? 0 : token_num
author_id = @pull_request.user_id
if token_num > 0
Blockchain::FixIssue.call({user_id: author_id.to_s, project_id: @project.id.to_s, token_num: token_num}) if Site.has_blockchain? && @project.use_blockchain
PullAttachedIssue.find_by(issue_id: issue.id, pull_request_id: @pull_request.id).update(fixed: true)
end
# update issue to state 5
issue.issue_participants.create!({participant_type: "edited", participant_id: current_user.id}) unless issue.issue_participants.exists?(participant_type: "edited", participant_id: current_user.id)
journal = issue.journals.create!({user_id: current_user.id})
journal.journal_details.create!({property: "attr", prop_key: "status_id", old_value: issue.status_id, value: 5})
issue.update(status_id: 5)
end
# 合并请求下issue处理为关闭

View File

@ -416,14 +416,14 @@ class UsersController < ApplicationController
is_current_admin_user = true
results = Blockchain::BalanceQuery.call(params, is_current_admin_user)
if results[:status] == 0
@total_count = results[:projects].size
@total_count = results[:total_count]
@projects = results[:projects]
else
@total_count = -1
@projects = []
end
render json: { status: results[:status], projects: @projects, total_count: @total_count }
# render json: { status: results[:status], projects: @projects, total_count: @total_count }
end
# query one balance

View File

@ -35,7 +35,7 @@ class BaseForm
end
def check_blockchain_init_token(blockchain_init_token)
raise "请正确填写项目创始人token占比." if (Float(blockchain_init_token) rescue false) == false or blockchain_init_token.to_i < 0 or blockchain_init_token.to_i > 100 or Float(blockchain_init_token) != blockchain_init_token.to_i
raise "请正确填写项目创始人token占比." if (Float(blockchain_init_token) rescue false) == false or blockchain_init_token.to_i < 0 or Float(blockchain_init_token) != blockchain_init_token.to_i
end
def check_reversed_keyword(repository_name)

View File

@ -66,6 +66,7 @@ module ProjectsHelper
jianmu_devops: jianmu_devops_code(project, user),
jianmu_devops_url: jianmu_devops_url,
cloud_ide_saas_url: cloud_ide_saas_url(user),
open_blockchain: Site.has_blockchain? && project.use_blockchain,
ignore_id: project.ignore_id
}).compact

20
app/libs/blockchain.rb Normal file
View File

@ -0,0 +1,20 @@
class Blockchain
class << self
def blockchain_config
blockchain_config = {}
begin
config = Rails.application.config_for(:configuration).symbolize_keys!
blockchain_config = config[:blockchain].symbolize_keys!
raise 'blockchain config missing' if blockchain_config.blank?
rescue => ex
raise ex if Rails.env.production?
puts %Q{\033[33m [warning] blockchain config or configuration.yml missing,
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
blockchain_config = {}
end
blockchain_config
end
end
end

View File

@ -31,11 +31,9 @@ module Watchable
following.size
end
def contribution_perc
project_identifier = params[:project_identifier]
user_login = params[:id]
@project = Project.find_by_identifier(project_identifier)
@user = User.find_by_login(user_login)
def contribution_perc(project)
@project = project
@user = self
def cal_perc(count_user, count_all)
(count_user * 1.0 / (count_all + 0.000000001)).round(5)

View File

@ -79,6 +79,8 @@ class Issue < ApplicationRecord
has_many :comment_journals, -> {where.not(notes: nil)}, class_name: "Journal", :as => :journalized
has_many :operate_journals, -> {where(notes: nil)}, class_name: "Journal", :as => :journalized
has_many :pull_attached_issues, dependent: :destroy
has_many :attach_pull_requests, through: :pull_attached_issues, source: :pull_request
scope :issue_includes, ->{includes(:user)}
scope :issue_many_includes, ->{includes(journals: :user)}

View File

@ -121,6 +121,10 @@ class Journal < ApplicationRecord
old_value = detail.old_value
new_value = detail.value
content += "结束日期"
when 'assigned_to_id'
old_value = User.find_by_id(detail.old_value)&.nickname
new_value = User.find_by_id(detail.value)&.nickname
content += "负责人"
end
if old_value.nil? || old_value.blank?
content += "设置为<b>#{new_value}</b>"

View File

@ -0,0 +1,23 @@
# == Schema Information
#
# Table name: pull_attached_issues
#
# id :integer not null, primary key
# pull_request_id :integer
# issue_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# fixed :boolean default("0")
#
# Indexes
#
# index_pull_attached_issues_on_issue_id (issue_id)
# index_pull_attached_issues_on_pull_request_id (pull_request_id)
#
class PullAttachedIssue < ApplicationRecord
belongs_to :pull_request
belongs_to :issue
end

View File

@ -44,6 +44,8 @@ class PullRequest < ApplicationRecord
has_many :pull_requests_reviewers, dependent: :destroy
has_many :reviewers, through: :pull_requests_reviewers
has_many :mark_files, dependent: :destroy
has_many :pull_attached_issues, dependent: :destroy
has_many :attached_issues, through: :pull_attached_issues, source: :issue
scope :merged_and_closed, ->{where.not(status: 0)}
scope :opening, -> {where(status: 0)}

View File

@ -30,6 +30,10 @@ class Site < ApplicationRecord
self.common.where(key: 'notice').present?
end
def self.has_blockchain?
self.common.where(key: 'blockchain').present?
end
private
def self.set_add_menu!
adds= [

View File

@ -8,17 +8,19 @@ class ApplicationQuery
end
# find all the repos that a user has tokens
def find_repo_with_token(user_id)
def find_repo_with_token(user_id, page=1, limit=10)
params = {
"request-type": "query user balance of all repos",
"username": user_id.to_s
"request-type": "query user balance of all repos by page",
"username": user_id.to_s,
"page": page.to_i,
"page_num": limit.to_i
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] != 0
raise "区块链接口请求失败."
else
token_list = resp_body['UserBalanceList'].nil? ? [] : resp_body['UserBalanceList']
return token_list
return token_list, resp_body['total_count']
end
end

View File

@ -9,21 +9,22 @@ class Blockchain::BalanceQuery < ApplicationQuery
def call
if is_current_admin_user
token_list = find_repo_with_token(params["user_id"])
token_list, total_count = find_repo_with_token(params["user_id"], (params["page"] || 1), (params["limit"] || 10))
result_list = []
token_list.each do |t|
project = Project.find_by(id: t['token_name'].to_i)
if project.nil?
result_list << {project: nil, balance: t['balance']}
next
end
owner = User.find_by(id: project.user_id)
if owner.nil? || project.nil?
else
balance = t['balance']
result_list << [owner, project, balance]
result_list << {project: project, balance: balance}
end
end
results = {"status": 0, "projects": result_list}
results = {"status": 0, "projects": result_list, "total_count": total_count}
else
results = {"status": 1} # query failed
end

View File

@ -39,7 +39,7 @@ class Projects::ListMyQuery < ApplicationQuery
# elsif params[:category].to_s == "private"
# projects = projects.is_private.joins(:members).where(members: { user_id: user.id })
elsif params[:category].to_s == "blockchain_token" # 所有钱包中有token的项目有哪些
token_list = find_repo_with_token(user.id)
token_list, total_count = find_repo_with_token(user.id)
project_names = token_list.map { |x| x['token_name'] }
projects = projects.where(name: project_names)
tokens = token_list.map { |x| x['balance'] }

View File

@ -45,4 +45,9 @@ module Api::V1::Issues::Concerns::Checkable
def check_parent_journal(parent_id)
raise ApplicationService::Error, "ParentJournal不存在" unless Journal.find_by_id(parent_id).present?
end
def check_blockchain_token_num(user_id, project_id, blockchain_token_num, now_blockchain_token_num=0)
left_blockchain_token_num = Blockchain::BalanceQueryOneProject.call({"user_id": user_id, "project_id": project_id}) rescue 0
raise ApplicationService::Error, "用户Token不足。" if blockchain_token_num.to_i > (left_blockchain_token_num+now_blockchain_token_num).to_i
end
end

View File

@ -4,13 +4,14 @@ class Api::V1::Issues::CreateService < ApplicationService
include Api::V1::Issues::Concerns::Loadable
attr_reader :project, :current_user
attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description
attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description, :blockchain_token_num
attr_reader :issue_tag_ids, :assigner_ids, :attachment_ids, :receivers_login
attr_accessor :created_issue
validates :subject, presence: true
validates :status_id, :priority_id, presence: true
validates :project, :current_user, presence: true
validates :blockchain_token_num, numericality: {greater_than: 0}, allow_blank: true
def initialize(project, params, current_user = nil)
@project = project
@ -23,6 +24,7 @@ class Api::V1::Issues::CreateService < ApplicationService
@due_date = params[:due_date]
@subject = params[:subject]
@description = params[:description]
@blockchain_token_num = params[:blockchain_token_num]
@issue_tag_ids = params[:issue_tag_ids]
@assigner_ids = params[:assigner_ids]
@attachment_ids = params[:attachment_ids]
@ -39,6 +41,7 @@ class Api::V1::Issues::CreateService < ApplicationService
check_assigners(assigner_ids) unless assigner_ids.blank?
check_attachments(attachment_ids) unless attachment_ids.blank?
check_atme_receivers(receivers_login) unless receivers_login.blank?
check_blockchain_token_num(current_user.id, project.id, blockchain_token_num) if blockchain_token_num.present?
load_assigners(assigner_ids) unless assigner_ids.blank?
load_attachments(attachment_ids) unless attachment_ids.blank?
load_issue_tags(issue_tag_ids) unless issue_tag_ids.blank?
@ -57,8 +60,20 @@ class Api::V1::Issues::CreateService < ApplicationService
@created_issue.issue_tags_value = @issue_tags.order("id asc").pluck(:id).join(",") unless issue_tag_ids.blank?
@created_issue.save!
if Site.has_blockchain? && @project.use_blockchain
if @created_issue.blockchain_token_num.present? && @created_issue.blockchain_token_num > 0
Blockchain::CreateIssue.call({user_id: current_user.id, project_id: @created_issue.project_id, token_num: @created_issue.blockchain_token_num})
end
push_activity_2_blockchain("issue_create", @created_issue)
end
project.del_project_issue_cache_delete_count # 把缓存里存储项目删除issue的个数清除掉
# 新增时向grimoirelab推送事件
IssueWebhookJob.set(wait: 5.seconds).perform_later(@created_issue.id)
# @信息发送
AtmeService.call(current_user, @atme_receivers, @created_issue) unless receivers_login.blank?
@ -94,6 +109,7 @@ class Api::V1::Issues::CreateService < ApplicationService
issue_attributes.merge!({start_date: start_date}) if start_date.present?
issue_attributes.merge!({due_date: due_date}) if due_date.present?
issue_attributes.merge!({branch_name: branch_name}) if branch_name.present?
issue_attributes.merge!({blockchain_token_num: blockchain_token_num}) if blockchain_token_num.present?
issue_attributes
end

View File

@ -19,6 +19,10 @@ class Api::V1::Issues::DeleteService < ApplicationService
project.incre_project_issue_cache_delete_count
if Site.has_blockchain? && @project.use_blockchain
unlock_balance_on_blockchain(@issue.author_id.to_s, @project.id.to_s, @issue.blockchain_token_num.to_i) if @issue.blockchain_token_num.present?
end
if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, @issue&.subject, @issue.assigners.pluck(:id), @issue.author_id)
end

View File

@ -39,6 +39,8 @@ class Api::V1::Issues::Journals::CreateService < ApplicationService
@created_journal.save!
@issue.save!
push_activity_2_blockchain("issue_comment_create", @created_journal) if Site.has_blockchain? && @issue.project&.use_blockchain
# @信息发送
AtmeService.call(current_user, @atme_receivers, @created_journal) unless receivers_login.blank?

View File

@ -1,18 +1,19 @@
class Api::V1::Issues::ListService < ApplicationService
include ActiveModel::Model
attr_reader :project, :category, :participant_category, :keyword, :author_id, :issue_tag_ids
attr_reader :project, :only_name, :category, :participant_category, :keyword, :author_id, :issue_tag_ids
attr_reader :milestone_id, :assigner_id, :status_id, :sort_by, :sort_direction, :current_user
attr_accessor :queried_issues, :total_issues_count, :closed_issues_count, :opened_issues_count
validates :category, inclusion: {in: %w(all opened closed), message: "请输入正确的Category"}
validates :participant_category, inclusion: {in: %w(all aboutme authoredme assignedme atme), message: "请输入正确的ParticipantCategory"}
validates :sort_by, inclusion: {in: ['issues.created_on', 'issues.updated_on', 'issue_priorities.position'], message: '请输入正确的SortBy'}, allow_blank: true
validates :sort_by, inclusion: {in: ['issues.created_on', 'issues.updated_on', 'issues.blockchain_token_num', 'issue_priorities.position'], message: '请输入正确的SortBy'}, allow_blank: true
validates :sort_direction, inclusion: {in: %w(asc desc), message: '请输入正确的SortDirection'}, allow_blank: true
validates :current_user, presence: true
def initialize(project, params, current_user=nil)
@project = project
@only_name = params[:only_name]
@category = params[:category] || 'all'
@participant_category = params[:participant_category] || 'all'
@keyword = params[:keyword]
@ -68,7 +69,7 @@ class Api::V1::Issues::ListService < ApplicationService
issues = issues.where(status_id: status_id) if status_id.present?
# keyword
issues = issues.ransack(subject_or_description_cont: keyword).result if keyword.present?
issues = issues.ransack(id_eq: keyword).result.or(issues.ransack(subject_or_description_cont: keyword).result) if keyword.present?
@total_issues_count = issues.distinct.size
@closed_issues_count = issues.closed.distinct.size
@ -81,9 +82,13 @@ class Api::V1::Issues::ListService < ApplicationService
issues = issues.opened
end
scope = issues.includes(:priority, :issue_status, :user, :show_assigners, :show_issue_tags, :version, :comment_journals)
scope = scope.reorder("#{sort_by} #{sort_direction}").distinct
if only_name.present?
scope = issues.select(:id, :subject, :project_issues_index)
scope = scope.reorder("project_issues_index asc").distinct
else
scope = issues.includes(:priority, :issue_status, :user, :show_assigners, :show_issue_tags, :version, :comment_journals)
scope = scope.reorder("#{sort_by} #{sort_direction}").distinct
end
@queried_issues = scope
end

View File

@ -4,11 +4,12 @@ class Api::V1::Issues::UpdateService < ApplicationService
include Api::V1::Issues::Concerns::Loadable
attr_reader :project, :issue, :current_user
attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description
attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description, :blockchain_token_num
attr_reader :issue_tag_ids, :assigner_ids, :attachment_ids, :receivers_login
attr_accessor :add_assigner_ids, :previous_issue_changes, :updated_issue, :atme_receivers
validates :project, :issue, :current_user, presence: true
validates :blockchain_token_num, numericality: {greater_than: 0}, allow_blank: true
def initialize(project, issue, params, current_user = nil)
@project = project
@ -22,6 +23,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
@due_date = params[:due_date]
@subject = params[:subject]
@description = params[:description]
@blockchain_token_num = params[:blockchain_token_num]
@issue_tag_ids = params[:issue_tag_ids]
@assigner_ids = params[:assigner_ids]
@attachment_ids = params[:attachment_ids]
@ -40,6 +42,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
check_assigners(assigner_ids) unless assigner_ids.nil?
check_attachments(attachment_ids) unless attachment_ids.nil?
check_atme_receivers(receivers_login) unless receivers_login.nil?
check_blockchain_token_num(issue.author_id, project.id, blockchain_token_num, (@issue.blockchain_token_num || 0)) if blockchain_token_num.present? && current_user.id == @issue.author_id && !PullAttachedIssue.exists?(issue_id: @issue, fixed: true)
load_assigners(assigner_ids)
load_attachments(attachment_ids)
load_issue_tags(issue_tag_ids)
@ -68,6 +71,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
build_after_issue_journal_details if @updated_issue.previous_changes.present? # 操作记录
build_previous_issue_changes
build_cirle_blockchain_token if blockchain_token_num.present?
# @信息发送
AtmeService.call(current_user, @atme_receivers, @issue) unless receivers_login.blank?
@ -86,6 +90,9 @@ class Api::V1::Issues::UpdateService < ApplicationService
private
def issue_load_attributes
if current_user.id == @updated_issue.author_id && !PullAttachedIssue.exists?(issue_id: @updated_issue, fixed: true)
@updated_issue.blockchain_token_num = blockchain_token_num unless blockchain_token_num.nil?
end
@updated_issue.status_id = status_id if status_id.present?
@updated_issue.priority_id = priority_id if priority_id.present?
@updated_issue.fixed_version_id = milestone_id unless milestone_id.nil?
@ -130,6 +137,13 @@ class Api::V1::Issues::UpdateService < ApplicationService
end
end
def build_cirle_blockchain_token
if @updated_issue.previous_changes["blockchain_token_num"].present?
unlock_balance_on_blockchain(@updated_issue&.author_id.to_s, @updated_issue.project_id.to_s, @updated_issue.previous_changes["blockchain_token_num"][0].to_i) if @updated_issue.previous_changes["blockchain_token_num"][0].present?
lock_balance_on_blockchain(@updated_issue&.author_id.to_s, @updated_issue.project_id.to_s, @updated_issue.previous_changes["blockchain_token_num"][1].to_i) if @updated_issue.previous_changes["blockchain_token_num"][1].present?
end
end
def build_issue_project_trends
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][1] == 5
@updated_issue.project_trends.new({user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE})

View File

@ -30,6 +30,8 @@ class Api::V1::Projects::Pulls::Journals::CreateService < ApplicationService
create_comment_journal
end
push_activity_2_blockchain("issue_comment_create", @journal) if Site.has_blockchain? && @project.use_blockchain
journal
end

View File

@ -33,7 +33,7 @@ class ApplicationService
username = params['user_id'].to_s
token_name = project.id.to_s
total_supply = params['blockchain_token_all'].to_i
token_balance = [[username, (total_supply * params['blockchain_init_token'].to_i / 100).to_i]]
token_balance = [[username, params['blockchain_init_token'].to_i]]
params = {
"request-type": "create repo",
@ -102,6 +102,324 @@ class ApplicationService
else
end
end
def push_activity_2_blockchain(activity_type, model)
if activity_type == "issue_create"
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return true
end
id = model['id']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
identifier = project['identifier']
author_id = project['user_id']
author = User.find(author_id)
username = author['login']
action = 'opened'
title = model['subject']
content = model['description']
created_at = model['created_on']
updated_at = model['updated_on']
# 调用区块链接口
params = {
"request-type": "upload issue info",
"issue_id": "gitlink-" + id.to_s,
"repo_id": "gitlink-" + project_id.to_s,
"issue_number": 0, # 暂时不需要改字段
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"title": title,
"content": content,
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
elsif activity_type == "issue_comment_create"
issue_comment_id = model['id']
issue_id = model['journalized_id']
parent_id = model['parent_id'].nil? ? "" : model['parent_id']
issue = Issue.find(issue_id)
issue_classify = issue['issue_classify'] # issue或pull_request
project_id = issue['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
author_id = model['user_id']
author = User.find(author_id)
username = author['login']
action = 'created'
content = model['notes']
created_at = model['created_on']
if issue_classify == "issue"
params = {
"request-type": "upload issue comment info",
"issue_comment_id": "gitlink-" + issue_comment_id.to_s,
"issue_comment_number": 0, # 暂时不需要
"issue_number": 0, # 暂时不需要
"issue_id": "gitlink-" + issue_id.to_s,
"repo_id": "gitlink-" + project.id.to_s,
"parent_id": parent_id.to_s,
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"content": content,
"created_at": created_at,
}.to_json
elsif issue_classify == "pull_request"
params = {
"request-type": "upload pull request comment info",
"pull_request_comment_id": "gitlink-" + issue_comment_id.to_s,
"pull_request_comment_number": 0, # 不考虑该字段
"pull_request_number": 0, # 不考虑该字段
"pull_request_id": "gitlink-" + issue_id.to_s,
"parent_id": parent_id.to_s,
"repo_id": "gitlink-" + project.id.to_s,
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"content": content,
"created_at": created_at,
}.to_json
end
# 调用区块链接口
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_create"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'opened'
title = model['title']
content = model['body']
source_branch = model['head']
source_repo_id = model['fork_project_id'].nil? ? project_id : model['fork_project_id']
target_branch = model['base']
target_repo_id = project_id
author_id = model['user_id']
author = User.find(author_id)
username = author['login']
created_at = model['created_at']
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'])
if commits.nil?
raise Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
commit_shas << c["Sha"]
end
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_merge"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'merged'
created_at = model['created_at']
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'])
if commits.nil?
raise Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
commit_shas << c["Sha"]
end
# 将pull request相关信息写入链上
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
# 将commit相关信息写入链上
commit_shas.each do |commit_sha|
commit_diff = Gitea::Commit::DiffService.call(ownername, identifier, commit_sha, owner['gitea_token'])
commit = Gitea::Commit::InfoService.call(ownername, identifier, commit_sha, owner['gitea_token'])
params = {
"request-type": "upload commit info",
"commit_hash": commit_sha,
"repo_id": "gitlink-" + project_id.to_s,
"author": commit['commit']['author']['name'],
"author_email": commit['commit']['author']['email'],
"committer": commit['commit']['committer']['name'],
"committer_email": commit['commit']['committer']['email'],
"author_time": commit['commit']['author']['date'],
"committer_time": commit['commit']['committer']['date'],
"content": commit['commit']['message'],
"commit_diff": commit_diff['Files'].to_s
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 7
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
end
elsif activity_type == "pull_request_refuse"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return true
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'refused'
# 将pull request相关信息写入链上
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
end
end
def phone_mail_type value
value =~ /^1\d{10}$/ ? 1 : 0
end

View File

@ -0,0 +1,40 @@
# get the diff info for the commit
class Gitea::Commit::DiffService < Gitea::ClientService
attr_reader :owner, :repo, :sha, :token
# GET /repos/{owner}/{repo}/commits/{sha}/diff
# owner: 用户
# repo: 仓库名称/标识
# sha: commit唯一标识
# eg:
# Gitea::Commit::DiffService.call('jasder', 'repo_identifier', 'sha value')
def initialize(owner, repo, sha, token=nil)
@owner = owner
@repo = repo
@sha = sha
@token = token
end
def call
response = get(url, params)
render_result(response)
end
private
def params
Hash.new.merge(token: token)
end
def url
"/repos/#{owner}/#{repo}/commits/#{sha}/diff".freeze
end
def render_result(response)
case response.status
when 200
JSON.parse(response.body)
else
nil
end
end
end

View File

@ -0,0 +1,39 @@
class Gitea::Commit::InfoService < Gitea::ClientService
attr_reader :owner, :repo, :sha, :token
# GET /repos/{owner}/{repo}/commits/{sha}/diff
# owner: 用户
# repo: 仓库名称/标识
# sha: commit唯一标识
# eg:
# Gitea::Commit::InfoService.call('jasder', 'repo_identifier', 'sha value', token='gitea token')
def initialize(owner, repo, sha, token=nil)
@owner = owner
@repo = repo
@sha = sha
@token = token
end
def call
response = get(url, params)
render_result(response)
end
private
def params
Hash.new.merge(token: token)
end
def url
"/repos/#{owner}/#{repo}/git/commits/#{sha}".freeze
end
def render_result(response)
case response.status
when 200
JSON.parse(response.body)
else
nil
end
end
end

View File

@ -20,6 +20,7 @@ class PullRequests::CreateService < ApplicationService
save_tiding!
save_project_trend!
save_custom_journal_detail!
save_pull_attached_issues!
end
[pull_request, gitea_pull_request]
@ -111,6 +112,20 @@ class PullRequests::CreateService < ApplicationService
end
end
def save_pull_attached_issues!
if attached_issue_ids.size > 1
raise "最多只能关联一个疑修。"
else
attached_issue_ids.each do |issue|
PullAttachedIssue.create!(issue_id: issue, pull_request_id: pull_request&.id)
end
end
end
def attached_issue_ids
Array(@params[:attached_issue_ids])
end
def gitea_pull_request
@gitea_pull_request ||= create_gitea_pull_request!
end

View File

@ -1,4 +1,5 @@
json.(issue, :id, :subject, :project_issues_index, :description, :branch_name, :start_date, :due_date)
json.blockchain_token_num issue.project&.use_blockchain ? issue.blockchain_token_num : nil
json.created_at issue.created_on.strftime("%Y-%m-%d %H:%M")
json.updated_at issue.updated_on.strftime("%Y-%m-%d %H:%M")
json.tags issue.show_issue_tags.each do |tag|
@ -42,4 +43,5 @@ json.comment_journals_count issue.comment_journals.size
json.operate_journals_count issue.operate_journals.size
json.attachments issue.attachments.each do |attachment|
json.partial! "api/v1/attachments/simple_detail", locals: {attachment: attachment}
end
end
json.pull_fixed issue.pull_attached_issues.where(fixed: true).present?

View File

@ -1,4 +1,5 @@
json.(issue, :id, :subject, :project_issues_index)
json.blockchain_token_num issue.project&.use_blockchain ? issue.blockchain_token_num : nil
json.created_at issue.created_on.strftime("%Y-%m-%d %H:%M")
json.updated_at issue.updated_on.strftime("%Y-%m-%d %H:%M")
json.tags issue.show_issue_tags.each do |tag|

View File

@ -12,4 +12,7 @@ json.issue_tag_ids @issue&.issue_tags_value&.split(",")
json.commits_count @pull_request.commits_count
json.files_count @pull_request.files_count
json.comments_count @pull_request.comments_count
json.reviewers @pull_request.reviewers.pluck(:login)
json.reviewers @pull_request.reviewers.pluck(:login)
json.attached_issues @pull_request.attached_issues.each do |issue|
json.(issue, :id, :subject, :project_issues_index)
end

View File

@ -38,6 +38,9 @@ json.issues do
json.version issue.version.try(:name)
json.journals_count issue.get_journals_size
json.issue_tags issue.get_issue_tags
json.attached_issues pr.attached_issues.each do |issue|
json.(issue, :id, :subject, :project_issues_index)
end
end
end

View File

@ -51,4 +51,8 @@ json.issue do
json.issue_tags @issue.get_issue_tags
end
json.attached_issues @pull_request.attached_issues.each do |issue|
json.(issue, :id, :subject, :project_issues_index)
end
json.conflict_files @pull_request.conflict_files

View File

@ -13,4 +13,6 @@ else
json.type user["type"]
json.name user["name"]
json.image_url user["avatar_url"]
db_user = User.find_by_id(user["id"])
json.contribution_perc db_user.contribution_perc(project) if db_user.present?
end

View File

@ -1,6 +1,6 @@
total_count = @contributors.size
json.list @contributors.each do |contributor|
json.partial! 'contributor', locals: { contributor: contributor }
json.partial! 'contributor', locals: { contributor: contributor, project: @project }
end
json.total_count total_count

View File

@ -0,0 +1,7 @@
json.total_count @total_count
json.projects @projects.each do |p|
if p[:project].present?
json.partial! 'projects/detail', locals: { project: p[:project] }
end
json.balance p[:balance]
end

View File

@ -258,6 +258,7 @@ Rails.application.routes.draw do
get :fan_users
get :hovercard
get :hovercard4proj # author: zxh, 获取用户对项目的贡献情况
get :contribution_perc
put :update_image
get :get_image
end

View File

@ -0,0 +1,10 @@
class CreatePullAttachedIssues < ActiveRecord::Migration[5.2]
def change
create_table :pull_attached_issues do |t|
t.references :pull_request
t.references :issue
t.timestamps
end
end
end

View File

@ -0,0 +1,5 @@
class AddFixedToPullAttachedIssues < ActiveRecord::Migration[5.2]
def change
add_column :pull_attached_issues, :fixed, :boolean, default: false
end
end