diff --git a/Gemfile b/Gemfile index cd6c4b91..abd202e9 100644 --- a/Gemfile +++ b/Gemfile @@ -125,3 +125,5 @@ gem 'request_store' gem 'harmonious_dictionary', '~> 0.0.1' gem 'parallel', '~> 1.19', '>= 1.19.1' + +gem 'alipay', '~> 0.15.1' diff --git a/Gemfile.lock b/Gemfile.lock index a6beea40..36896d5a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -52,6 +52,7 @@ GEM activerecord (>= 3.0) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) + alipay (0.15.2) ancestry (3.0.7) activerecord (>= 3.2.0) annotate (2.6.5) @@ -424,6 +425,7 @@ DEPENDENCIES active_decorator acts-as-taggable-on (~> 6.0) acts_as_list + alipay (~> 0.15.1) ancestry annotate (~> 2.6.0) awesome_print @@ -491,4 +493,4 @@ DEPENDENCIES wkhtmltopdf-binary BUNDLED WITH - 2.1.4 + 2.2.3 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ee47563c..97c5f0eb 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -817,6 +817,34 @@ class ApplicationController < ActionController::Base # author: zxh # blockchain存证api + #def invoke_blockchain_api(uri, params) + # begin + # uri = URI.parse(URI.encode(uri.strip)) + # res = Net::HTTP.start(uri.host, uri.port) do |http| + # req = Net::HTTP::Post.new(uri) + # req['Content-Type'] = 'application/json' + # req.body = params + # http.request(req) + # end + # if res.code.to_i != 200 + # puts '区块链接口请求失败.' + # return false + # else + # res_body = JSON.parse(res.body) + # if res_body.has_key?("data") && JSON.parse(res_body["data"]).has_key?("status") && JSON.parse(res_body["data"])['status'] == "Success" + # else + # puts '区块链接口请求出错.' + # return false + # end + # end + # + # return true + # rescue Exception => e + # puts '区块链接口请求失败.' + # return false + # end + #end + def invoke_blockchain_api(uri, params) begin uri = URI.parse(URI.encode(uri.strip)) @@ -831,7 +859,7 @@ class ApplicationController < ActionController::Base return false else res_body = JSON.parse(res.body) - if res_body.has_key?("data") && JSON.parse(res_body["data"]).has_key?("status") && JSON.parse(res_body["data"])['status'] == "Success" + if res_body.has_key?("status") && res_body["status"] == 0 else puts '区块链接口请求出错.' return false @@ -845,6 +873,7 @@ class ApplicationController < ActionController::Base end end + # author: zxh # blockchain相关项目活动调用函数 # return true: 表示上链操作成功; return false: 表示上链操作失败 diff --git a/app/controllers/blockchain/base_controller.rb b/app/controllers/blockchain/base_controller.rb new file mode 100644 index 00000000..40630730 --- /dev/null +++ b/app/controllers/blockchain/base_controller.rb @@ -0,0 +1,48 @@ +class Blockchain::BaseController < ApplicationController + + before_action :require_login + before_action :connect_to_ci_database, if: -> { current_user && !current_user.is_a?(AnonymousUser) && !current_user.devops_uninit? } + before_action :connect_to_ci_database, only: :load_repo + + + def load_repo + namespace = params[:owner] + id = params[:repo] || params[:id] + + @ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id) + end + + private + def authorize_access_project! + unless @project.manager?(current_user) + return render_forbidden + end + end + + def authenticate_manager! + unless @project.manager?(current_user) + return render_forbidden + end + end + + def authenticate_admin! + return render_forbidden unless current_user.admin? + end + + def authorize_owner! + unless @project.owner?(current_user) + return render_forbidden + end + end + + def find_cloud_account + @cloud_account ||= current_user.ci_cloud_account + @cloud_account.blank? ? nil : @cloud_account + end + + def load_ci_user + @ci_user ||= Ci::User.find_by(user_login: params[:owner]) + @ci_user.blank? ? raise("未找到相关的记录") : @ci_user + end + +end \ No newline at end of file diff --git a/app/controllers/blockchains_controller.rb b/app/controllers/blockchains_controller.rb new file mode 100644 index 00000000..4f0d78ea --- /dev/null +++ b/app/controllers/blockchains_controller.rb @@ -0,0 +1,7 @@ +class BlockchainController < ApplicationController + + def get_issue_token_num + puts "pause" + end + +end \ No newline at end of file diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index eb0ca595..679a57ef 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -141,14 +141,22 @@ class IssuesController < ApplicationController @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") # author: zxh - # 调用上链API - success_blockchain = push_activity_2_blockchain("issue_create", @issue) - if success_blockchain == false + # 扣除发起人的token + blockchain_result = Blockchain::CreateIssue.call(user_id: @issue.author_id, project_id: @issue.project_id, token_num: @issue.blockchain_token_num) + if blockchain_result = false normal_status(-1, "创建失败") raise ActiveRecord::Rollback else - render json: {status: 0, message: "创建成功", id: @issue.id} end + render json: {status: 0, message: "创建成功", id: @issue.id} + # 调用上链API + #success_blockchain = push_activity_2_blockchain("issue_create", @issue) + #if success_blockchain == false + # normal_status(-1, "创建失败") + # raise ActiveRecord::Rollback + #else + # render json: {status: 0, message: "创建成功", id: @issue.id} + #end else normal_status(-1, "创建失败") raise ActiveRecord::Rollback @@ -468,7 +476,8 @@ class IssuesController < ApplicationController branch_name: params[:branch_name].to_s, issue_classify: "issue", author_id: current_user.id, - project_id: @project.id + project_id: @project.id, + blockchain_token_num: params[:blockchain_token_num] } end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e19e8a04..8c6b6c6f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -163,7 +163,7 @@ class ProjectsController < ApplicationController private def project_params params.permit(:user_id, :name, :description, :repository_name, - :project_category_id, :project_language_id, :license_id, :ignore_id, :private, :blockchain) + :project_category_id, :project_language_id, :license_id, :ignore_id, :private, :blockchain, :blockchain_token_all, :blockchain_init_token) end def mirror_params diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 6551bf9a..1bc12da4 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -57,13 +57,14 @@ class PullRequestsController < ApplicationController # author: zxh # 调用上链API - success_blockchain = push_activity_2_blockchain("pull_request_create", @pull_request) - if success_blockchain == false - render_error("create pull request error: cannot save to blockchain") - raise ActiveRecord::Rollback - else - render_ok - end + #success_blockchain = push_activity_2_blockchain("pull_request_create", @pull_request) + #if success_blockchain == false + # render_error("create pull request error: cannot save to blockchain") + # raise ActiveRecord::Rollback + #else + # render_ok + #end + render_ok else render_error("create pull request error: #{@gitea_pull_request[:status]}") @@ -178,14 +179,46 @@ class PullRequestsController < ApplicationController # author: zxh # 调用上链API - success_blockchain = push_activity_2_blockchain("pull_request_merge", @pull_request) - if success_blockchain == false - normal_status(-1, "合并失败") - raise ActiveRecord::Rollback - else - normal_status(1, "合并成功") - end + #success_blockchain = push_activity_2_blockchain("pull_request_merge", @pull_request) + #if success_blockchain == false + # normal_status(-1, "合并失败") + # raise ActiveRecord::Rollback + #else + # normal_status(1, "合并成功") + #end + # + # 查看是否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失败") + 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失败") + else + project = Project.find_by(user_id: owner.id, name: params["project_id"]) + if project.nil? + normal_status(-1, "关联issue失败") + else + author_id = pr.user_id + result = Blockchain::FixIssue.call({user_id: author_id.to_s, project_id: project.id.to_s, token_num: token_num}) + if result == false + normal_status(-1, "关联issue失败") + else + # update issue to state 5 + issue.update(status_id: 5) + normal_status(1, "合并成功") + end + end + end + end + end else normal_status(-1, "合并失败") end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 63e65a38..21acc500 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -203,6 +203,226 @@ class UsersController < ApplicationController @projects = paginate(scope) end + + # query all projects with tokens by a user + def blockchain_balance + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + results = Blockchain::BalanceQuery.call(params, is_current_admin_user) + if results[:status] == 0 + @total_count = results[:projects].size + @projects = results[:projects] + else + @total_count = -1 + @projects = [] + end + + render json: { status: results[:status], projects: @projects, total_count: @total_count } + end + + # query one balance + def blockchain_balance_one_project + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + if is_current_admin_user + owner = User.find_by(login: params['owner_login']) + if owner.nil? + raise Error, "项目创建者无法找到" + else + p = Project.find_by(user_id: owner.id, name: params['project_name']) + results = Blockchain::BalanceQueryOneProject.call({"user_id": params['user_id'].to_i, "project_id": p.id.to_i}) + render json: { status: results[:status], balance: results[:balance]} + end + else + raise Error, '没有权限' + end + + end + + + def blockchain_transfer + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['payer_id'].to_i) + if is_current_admin_user + results = Blockchain::TransferService.call(params) + if results == true + render json: { status: 2 } # 重新查询余额 + else + raise Error, "转账失败" + end + else + raise Error, "缺少权限" + end + end + + # exchange money + def blockchain_exchange + #is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + #require 'alipay' + ## setup the client to communicate with either production API or sandbox API + ## https://openapi.alipay.com/gateway.do (Production) + ## https://openapi.alipaydev.com/gateway.do (Sandbox) + #api_url = 'https://openapi.alipay.com/gateway.do' + # + ## setup your own credentials and certificates + #app_id = '2021002140631434' + #app_private_key="-----BEGIN RSA PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCPDsgc0n0RWRnbe9OMqtUbde8gu88OyjuZm8cJXeiSING18HX56C5zV4DsHQ6K9/JmQi/NYCc7/2Prh66Bei0L4Xm5TysJTPYi90+WlbJJESFF6fqULi8sSqZXUtaoMKRcUyeR144l2GQgXbZWBbVSQeZW5DqUDlurTF0I7vQ21wGqxQqBjQK8PSVw5hF+aIsNOfAY9M1tzdD5Jzo2Y3FJdsbXIJNMyhJJCZ+7KHFqma7lpjkXdCoyh/nOISkQdGtFI29gI94sqewI2AMU84uxuBIE3h90iLT+8xrd2dQKdBS7qfhQ3PgkBPVNs5jxsVBqSFdSFT6zcqFdHJzulCUJAgMBAAECggEAWocAGz0X5+J6emnhdSKluLrol85BORrAnHP3f/XtNouOKZQBFCPZQSQecUvx5/7/ZbZ8iXpPWahDkshJpaWq29nTLXDryvboyze1JZWVPKeaZqOp7htLvrt+h8PkEoq1d7cnUyMU0N4eflzPBaCXHXaWTGYgq5Bqcfvg48ZSxGBYeHt5WWU2+GW5fpsaVBBYkdyxxGMoy/bzYzGhvfSJkexqnl0XkAAODa02mu3WsHrzRid6Mf+3syYbq/MfUodU6Vng2tbCqwnWrHCyrD4RYl6rg1TKuAv2YAfBhLzwBxHYVC4SRqzjs+8AaOQoF+lCjr4JklPhEuRThzD31YwIAQKBgQDAg4S7ciMmxvbNxR+1eimoAYLLF9jPpPU6w3VFNPb4rDu4tX77bNf082YplfJX5TYtZKjKPKyYG87K6slGunyPL4AFRW81WPB9u1uP26dihyPCBSUE01jKRPPfRrQnnru5fpm8LL3L03V3yA6J+GyQ8wltRJJi1eBSSm+IWRsZewKBgQC+PBD9J1LYOEIVeK9KvN8BpkA1ZIkk//VuJaoGfVXn+1EzM1yFB05fnsEQkHFynisvuCIr7pH63HcdyffQhe1YOnw9iDCG1zPjsi5uTe9WAM0dnb7xdsaLPr/Q2LyoDOTN9344Qovy1AAnpWtGTn6omgHst5nZpp/mHOuBlKiqSwKBgBKRXM77fjpyPEGyfpFxW+0xYB0YirfUUDa/vWLUbfGkIwp4ruuvHtEoXLUsGjiyCdys9b6zxW3SWMqnhIxG1la1HSLlBInfryphVL52UBmnsSI4fs6NV+YCaocheaTMoYyNkmRc6F1tYsoPyJ80D7yXRFR+paPUvxMQzNsYxQ1bAoGAHd2uSSBQWFPUxCwzUQd/93FTaU6EXYO103okTGqG/ymsoN4ya0wvWMHCy8fxl64PV6mP69fDoV/Vb57SwjEUhyJ/eOWVwMWuhtPliDnCFn1/tmOao6wjFZ9fW/l6/OMxVMjDTy/bat8vuwm0YtBWAEBVhwV4KPyI5AasTqa5KCsCgYB/usnqhVx2zt+MxpBt2Q9Vxc0zXcZxMDs69UUdTY86gjcJyCFGe3bbumUcyfSJzIznC2hfFX5ZyS0oMwiAzWtslRMh9LRh3kofD/6BogL3RKOlBk3iekvQ8Gn0tbwk2Qzr4WJgfA7A4GTf5r7Y+bvOfazzsUQAfSK6nUTIlOj2Ew==\n-----END RSA PRIVATE KEY-----\n" + #alipay_public_key="-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgHXLD1BshMymbqqtZVKNyo95FNfxzXzaw3P1eI0KeO6RaL+JzrWxzIBFfTjkWv/8WM9u/NcXMOFt2QO9q5KIDx6PkqjRDTd1hgP/cTgdjOHQqnVSihCrQDVCDBSOXIujC8Lk/P4pFVRhQkYeZqEb1qb8b/2tzTY8g9PKKBSCQv7SfgL2TBcpAVbb+9xdJ6VainC/wYGk8T+c+st1hXnuBJSS0m7LFxJOsYkNk0wbA0tfdZLrO3us2F7sjC9t4h/05nr+gSuDkzo+1kCEefYLqScexN+vnQiLoylp/C82wNiP6okxfhmHz3EcYfUqUyGTN/oFaFcPFPpUtFNS8jFV9QIDAQAB\n-----END PUBLIC KEY-----\n" + # + ## initialize a client to communicate with the Alipay API + #@alipay_client = Alipay::Client.new( + # url: api_url, + # app_id: app_id, + # app_private_key: app_private_key, + # alipay_public_key: alipay_public_key + #) + # + #return_result = @alipay_client.page_execute_url( + # method: 'alipay.trade.page.pay', + # biz_content: JSON.generate({ + # out_trade_no: '20210420104600', + # product_code: 'FAST_INSTANT_TRADE_PAY', + # total_amount: '0.01', + # subject: 'test' + # }, ascii_only: true), # ascii_only is important! + # timestamp: '2021-04-20 10:46:00' + #) + #render json: { pay_url: return_result } + # + + # 替代解决方案 + # 读取所有交易信息 + end + + def blockchain_create_trade + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + if is_current_admin_user + user_id = params['user_id'].to_i + project_id = params['project_id'].to_i + money = params['money'].to_f + #description = params['description'] + token_num = params['token_num'].to_i + # 锁仓 + result = Blockchain::CreateTrade.call({user_id: user_id, project_id: project_id, token_num: token_num}) + if result == false + raise Error, "创建交易失败" + else + bt = BlockchainTrade.new(user_id: user_id, project_id: project_id, token_num: token_num, money: money, state: 0) # state=0表示创建交易; state=1表示执行中; state=2表示执行完成 + bt.save() + status = 2 # 交易创建成功 + render json: { status: status } + end + else + raise Error, "没有权限" + end + end + + + def blockchain_get_trades + trades = BlockchainTrade.where(state: 0).all() + results = [] + trades.each do |t| + project_id = t.project_id + project = Project.find_by(id: project_id) + if !project.nil? + owner = User.find_by(id: project.user_id) + else + owner = nil + end + user_id = t.user_id + creator = User.find_by(id: user_id) + if project.nil? || owner.nil? || creator.nil? + else + results << [creator, owner, project, t] + end + end + render json: { results: results } + end + + def blockchain_trade + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + if is_current_admin_user + user_id2 = params['user_id2'].to_i + trade_id = params['trade_id'].to_i + BlockchainTrade.find(trade_id).update(user_id2: user_id2, state: 1) # state=1表示锁定了,等待线下卖家发货 + render json: {status: 2} # window.location.reload() + else + raise Error, "没有权限" + end + end + + + def blockchain_verify_trade + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + if is_current_admin_user + trade_id = params['trade_id'].to_i + BlockchainTrade.find(trade_id).update(state: 2) # state=2表示确认收货 + render json: {status: 2} # window.location.reload() + else + raise Error, "没有权限" + end + end + + def blockchain_get_verify_trades + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + if is_current_admin_user + trades = BlockchainTrade.where(state: 1).all() + results = [] + trades.each do |t| + project_id = t.project_id + project = Project.find_by(id: project_id) + if !project.nil? + owner = User.find_by(id: project.user_id) + else + owner = nil + end + user_id = t.user_id + creator = User.find_by(id: user_id) + user_id2 = t.user_id2 + buyer = User.find_by(id: user_id2) + if project.nil? || owner.nil? || creator.nil? || buyer.nil? + else + results << [creator, owner, project, t, buyer] + end + end + render json: { results: results } + else + raise Error, "没有权限" + end + end + + def blockchain_get_history_trades + is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i) + if is_current_admin_user + trades = BlockchainTrade.where(state: 2).all() + results = [] + trades.each do |t| + project_id = t.project_id + project = Project.find_by(id: project_id) + if !project.nil? + owner = User.find_by(id: project.user_id) + else + owner = nil + end + user_id = t.user_id + creator = User.find_by(id: user_id) + user_id2 = t.user_id2 + buyer = User.find_by(id: user_id2) + if project.nil? || owner.nil? || creator.nil? || buyer.nil? + else + results << [creator, owner, project, t, buyer] + end + end + render json: { results: results } + else + raise Error, "没有权限" + end + end + + + def blockchain_get_issue_token_num + issue_id = params["issue_id"]['orderId'].to_i + issue = Issue.find_by(id: issue_id) + render json: {"blockchain_token_num": issue.blockchain_token_num} + end + # TODO 其他平台登录时同步修改gitea平台对应用户的密码 # 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题 def sync_gitea_pwd diff --git a/app/forms/projects/create_form.rb b/app/forms/projects/create_form.rb index fd303f61..4f4b4f77 100644 --- a/app/forms/projects/create_form.rb +++ b/app/forms/projects/create_form.rb @@ -1,7 +1,8 @@ class Projects::CreateForm < BaseForm REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, - :project_language_id, :ignore_id, :license_id, :private, :blockchain + :project_language_id, :ignore_id, :license_id, :private, + :blockchain, :blockchain_token_all, :blockchain_init_token validates :user_id, :name, :description,:repository_name, :project_category_id, :project_language_id, presence: true diff --git a/app/helpers/tag_chosen_helper.rb b/app/helpers/tag_chosen_helper.rb index afd51170..f1bed85d 100644 --- a/app/helpers/tag_chosen_helper.rb +++ b/app/helpers/tag_chosen_helper.rb @@ -20,7 +20,7 @@ module TagChosenHelper "done_ratio": render_complete_percentage, "issue_tag": render_issue_tags(project), "issue_type": render_issue_species, - "all_issues": all_issues + "all_issues": all_issues, } end diff --git a/app/models/blockchain_trade.rb b/app/models/blockchain_trade.rb new file mode 100644 index 00000000..3d1f7597 --- /dev/null +++ b/app/models/blockchain_trade.rb @@ -0,0 +1,18 @@ +# == Schema Information +# +# Table name: blockchain_trades +# +# id :integer not null, primary key +# project_id :integer +# description :text(65535) +# money :float(24) +# created_at :datetime not null +# updated_at :datetime not null +# user_id :integer +# state :integer +# user_id2 :integer +# token_num :integer +# + +class BlockchainTrade < ApplicationRecord +end diff --git a/app/models/issue.rb b/app/models/issue.rb index 934e1d31..aa849312 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -33,6 +33,7 @@ # issue_classify :string(255) # ref_name :string(255) # branch_name :string(255) +# blockchain_token_num :integer # # Indexes # @@ -73,7 +74,6 @@ class Issue < ApplicationRecord scope :issue_issue, ->{where(issue_classify: [nil,"issue"])} scope :issue_pull_request, ->{where(issue_classify: "pull_request")} scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)} - after_update :change_versions_count after_destroy :update_closed_issues_count_in_project! diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb index 73002a84..699800c9 100644 --- a/app/models/laboratory.rb +++ b/app/models/laboratory.rb @@ -11,6 +11,11 @@ # sync_subject :boolean default("0") # sync_shixun :boolean default("0") # +# Indexes +# +# index_laboratories_on_identifier (identifier) UNIQUE +# index_laboratories_on_school_id (school_id) +# class Laboratory < ApplicationRecord belongs_to :school, optional: true diff --git a/app/models/laboratory_setting.rb b/app/models/laboratory_setting.rb index 5013dd54..61c677de 100644 --- a/app/models/laboratory_setting.rb +++ b/app/models/laboratory_setting.rb @@ -6,6 +6,10 @@ # laboratory_id :integer # config :text(65535) # +# Indexes +# +# index_laboratory_settings_on_laboratory_id (laboratory_id) +# class LaboratorySetting < ApplicationRecord belongs_to :laboratory diff --git a/app/queries/application_query.rb b/app/queries/application_query.rb index c66af94c..5029da75 100644 --- a/app/queries/application_query.rb +++ b/app/queries/application_query.rb @@ -6,4 +6,61 @@ class ApplicationQuery def strip_param(key) params[key].to_s.strip.presence end + + + # author: zxh + # add blockchain related functions in application_query + + def invoke_blockchain_api(uri, params) + begin + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.start(uri.host, uri.port) do |http| + req = Net::HTTP::Post.new(uri) + req['Content-Type'] = 'application/json' + req.body = params + http.request(req) + end + if res.code.to_i != 200 + puts '区块链接口请求失败.' + return false + else + res_body = JSON.parse(res.body) + if res_body.has_key?("status") && res_body["status"] == 0 + else + puts '区块链接口请求出错.' + return false + end + end + + return res_body + rescue Exception => e + puts '区块链接口请求失败.' + return false + end + end + + + # find all the repos that a user has tokens + def find_repo_with_token(user_id) + param = { + "request-type": "query user balance of all repos", + "username": user_id.to_s + }.to_json + resp_body = invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + token_list = resp_body['UserBalanceList'].nil? ? [] : resp_body['UserBalanceList'] + return token_list + end + + + # find one repo that a user has tokens + def find_one_balance(user_id, project_id) + param = { + "request-type": "query user balance of single repo", + "username": user_id.to_s, + "token_name": project_id.to_s + }.to_json + resp_body = invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + return resp_body + end + end \ No newline at end of file diff --git a/app/queries/blockchain/balance_query.rb b/app/queries/blockchain/balance_query.rb new file mode 100644 index 00000000..1c00152e --- /dev/null +++ b/app/queries/blockchain/balance_query.rb @@ -0,0 +1,28 @@ +class Blockchain::BalanceQuery < ApplicationQuery + + attr_reader :params, :is_current_admin_user + + def initialize(params,is_current_admin_user) + @params = params + @is_current_admin_user = is_current_admin_user + end + + def call + if is_current_admin_user + token_list = find_repo_with_token(params["user_id"]) + result_list = [] + token_list.each do |t| + owner = User.find_by(id: t['username'].to_i) + project = Project.find_by(id: t['token_name'].to_i) + if owner.nil? || project.nil? + else + balance = t['balance'] + result_list << [owner, project, balance] + end + end + results = {"status": 0, "projects": result_list} + else + results = {"status": 1} # query failed + end + end +end diff --git a/app/queries/blockchain/balance_query_one_project.rb b/app/queries/blockchain/balance_query_one_project.rb new file mode 100644 index 00000000..2cdb71dd --- /dev/null +++ b/app/queries/blockchain/balance_query_one_project.rb @@ -0,0 +1,13 @@ +class Blockchain::BalanceQueryOneProject < ApplicationQuery + + attr_reader :params, :is_current_admin_user + + def initialize(params) + @params = params + end + + def call + balance = find_one_balance(params[:user_id].to_s, params[:project_id].to_s) + results = {"status": balance['status'], "balance": balance['balance']} + end +end diff --git a/app/queries/projects/list_my_query.rb b/app/queries/projects/list_my_query.rb index ba521e90..c59228b2 100644 --- a/app/queries/projects/list_my_query.rb +++ b/app/queries/projects/list_my_query.rb @@ -37,6 +37,12 @@ class Projects::ListMyQuery < ApplicationQuery # projects = projects.visible.joins(:members).where(members: { user_id: user.id }) # 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) + project_names = token_list.map { |x| x['token_name'] } + projects = projects.where(name: project_names) + tokens = token_list.map { |x| x['balance'] } + puts "pause" end if params[:project_type].to_s === "common" diff --git a/app/services/application_service.rb b/app/services/application_service.rb index 2fa59ed2..cac2da1c 100644 --- a/app/services/application_service.rb +++ b/app/services/application_service.rb @@ -18,4 +18,95 @@ class ApplicationService def str_to_boolean str ActiveModel::Type::Boolean.new.cast str end + + + # author: zxh + # blockchain创建项目相关api + + def invoke_blockchain_api(uri, params) + begin + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.start(uri.host, uri.port) do |http| + req = Net::HTTP::Post.new(uri) + req['Content-Type'] = 'application/json' + req.body = params + http.request(req) + end + if res.code.to_i != 200 + puts '区块链接口请求失败.' + return false + else + res_body = JSON.parse(res.body) + if res_body.has_key?("status") && res_body["status"] == 0 + else + puts '区块链接口请求出错.' + return false + end + end + + return true + rescue Exception => e + puts '区块链接口请求失败.' + return false + end + end + + + # params: params from index.js page + def create_repo_on_blockchain(params, project) + username = params['user_id'].to_s + token_name = project.id.to_s + total_supply = params['blockchain_token_all'].to_i + token_balance = [[username, params['blockchain_init_token'].to_i]] + + param = { + "request-type": "create repo", + "username": username, + "token_name": token_name, + "total_supply": total_supply, + "token_balance": token_balance + }.to_json + invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + end + + + def transfer_balance_on_blockchain(payer, payee, token_name, amount) + + param = { + "request-type": "transfer amount", + "payer": payer, + "payee": payee, + "token_name": token_name, + "amount": amount + }.to_json + results = invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + return results + end + + + def lock_balance_on_blockchain(username, tokenname, amount) + + param = { + "request-type": "lock user balance", + "username": username, + "token_name": tokenname, + "amount": amount + }.to_json + results = invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + return results + end + + + def unlock_balance_on_blockchain(username, tokenname, amount) + + param = { + "request-type": "unlock user balance", + "username": username, + "token_name": tokenname, + "amount": amount + }.to_json + results = invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + return results + end + end diff --git a/app/services/blockchain/create_issue.rb b/app/services/blockchain/create_issue.rb new file mode 100644 index 00000000..286f6eda --- /dev/null +++ b/app/services/blockchain/create_issue.rb @@ -0,0 +1,29 @@ +class Blockchain::CreateIssue < ApplicationService + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + ActiveRecord::Base.transaction do + username = @params[:user_id].to_s + token_name = @params[:project_id].to_s + amount = @params[:token_num].to_i + + # 调用token锁仓函数 + results = lock_balance_on_blockchain(username, token_name, amount) + return results + end + rescue => e + puts "转账失败: #{e.message}" + raise Error, e.message + end + + private + + def no_use + puts "this function does not have any usage" + end +end \ No newline at end of file diff --git a/app/services/blockchain/create_trade.rb b/app/services/blockchain/create_trade.rb new file mode 100644 index 00000000..a4de9878 --- /dev/null +++ b/app/services/blockchain/create_trade.rb @@ -0,0 +1,29 @@ +class Blockchain::CreateTrade < ApplicationService + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + ActiveRecord::Base.transaction do + username = @params[:user_id].to_s + token_name = @params[:project_id].to_s + amount = @params[:token_num].to_i + + # 调用token锁仓函数 + results = lock_balance_on_blockchain(username, token_name, amount) + return results + end + rescue => e + puts "转账失败: #{e.message}" + raise Error, e.message + end + + private + + def no_use + puts "this function does not have any usage" + end +end \ No newline at end of file diff --git a/app/services/blockchain/fix_issue.rb b/app/services/blockchain/fix_issue.rb new file mode 100644 index 00000000..573db88e --- /dev/null +++ b/app/services/blockchain/fix_issue.rb @@ -0,0 +1,29 @@ +class Blockchain::FixIssue < ApplicationService + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + ActiveRecord::Base.transaction do + username = @params[:user_id].to_s + token_name = @params[:project_id].to_s + amount = @params[:token_num].to_i + + # 调用token锁仓函数 + results = unlock_balance_on_blockchain(username, token_name, amount) + return results + end + rescue => e + puts "关联issue失败: #{e.message}" + raise Error, e.message + end + + private + + def no_use + puts "this function does not have any usage" + end +end \ No newline at end of file diff --git a/app/services/blockchain/transfer_service.rb b/app/services/blockchain/transfer_service.rb new file mode 100644 index 00000000..fe61477d --- /dev/null +++ b/app/services/blockchain/transfer_service.rb @@ -0,0 +1,35 @@ +class Blockchain::TransferService < ApplicationService + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + ActiveRecord::Base.transaction do + transfer_amount = params['transfer_amount'].to_i + transfer_login = params['transfer_login'] + payer = params['payer_id'].to_s + payee = User.find_by(login: transfer_login) + if payee.nil? + raise Error, "未找到用户" + else + payee = payee.id.to_s + token_name = params['project_id'].to_s + # 调用token转移函数 + results = transfer_balance_on_blockchain(payer, payee, token_name, transfer_amount) + return results + end + end + rescue => e + puts "转账失败: #{e.message}" + raise Error, e.message + end + + private + + def no_use + puts "this function does not have any usage" + end +end \ No newline at end of file diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb index 728a9809..6a77c511 100644 --- a/app/services/gitea/client_service.rb +++ b/app/services/gitea/client_service.rb @@ -77,7 +77,7 @@ class Gitea::ClientService < ApplicationService puts "[gitea] token: #{token}" @client ||= begin - Faraday.new(url: domain) do |req| + Faraday.new(url: domain+":3000") do |req| req.request :url_encoded req.headers['Content-Type'] = 'application/json' req.response :logger # 显示日志 @@ -102,7 +102,7 @@ class Gitea::ClientService < ApplicationService end def api_url - [domain, base_url].join('') + [domain+":3000", base_url].join('') end def full_url(api_rest, action='post') diff --git a/app/services/gitea/repository/create_service.rb b/app/services/gitea/repository/create_service.rb index 168aaab2..f4b282ed 100644 --- a/app/services/gitea/repository/create_service.rb +++ b/app/services/gitea/repository/create_service.rb @@ -25,7 +25,7 @@ class Gitea::Repository::CreateService < Gitea::ClientService private def request_params - create_params = params.merge(readme: "readme") + create_params = params.merge(readme: "", default_branch: "master", issue_labels:"") # change readme to "" 暂时地 Hash.new.merge(token: token, data: create_params) end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 0cb10073..34ca2dd2 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -14,6 +14,10 @@ class Projects::CreateService < ApplicationService if @project.save! Project.update_common_projects_count! Repositories::CreateService.new(user, @project, repository_params).call + + # insert related tokens number and percentage of init tokens on blockchain + create_repo_on_blockchain(params, @project) + else Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}") end diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index 9458e513..46a52d64 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -64,7 +64,8 @@ class Repositories::CreateService < ApplicationService name: params[:identifier], private: params[:hidden], # readme: "ReadMe", - "auto_init": true, + auto_init: true, + description: @project.description # "description": "string", # "gitignores": "string", # "issue_labels": "string", diff --git a/config/routes.rb b/config/routes.rb index 145c20a7..8ac121cd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Rails.application.routes.draw do - + require 'sidekiq/web' require 'admin_constraint' @@ -68,6 +68,18 @@ Rails.application.routes.draw do put 'commons/unhidden', to: 'commons#unhidden' delete 'commons/delete', to: 'commons#delete' + get 'users/blockchain/balance', to: 'users#blockchain_balance' + post 'users/blockchain/balance_project', to: 'users#blockchain_balance_one_project' + post 'users/blockchain/transfer', to: 'users#blockchain_transfer' + post 'users/blockchain/exchange', to: 'users#blockchain_exchange' + post 'users/blockchain/create_trade', to: 'users#blockchain_create_trade' + get '/users/blockchain/get_trades', to: 'users#blockchain_get_trades' + post '/users/blockchain/trade', to: 'users#blockchain_trade' + get '/users/blockchain/get_verify_trades', to: 'users#blockchain_get_verify_trades' + post '/users/blockchain/verify_trade', to: 'users#blockchain_verify_trade' + get '/users/blockchain/get_history_trades', to: 'users#blockchain_get_history_trades' + post '/blockchain/issue/get_token_num', to: 'users#blockchain_get_issue_token_num' + resources :issues, except: [:index, :new,:create, :update, :edit, :destroy] do resources :journals, only: [:index, :create, :destroy, :edit, :update] do member do diff --git a/db/migrate/20210420043449_create_blockchain_trades.rb b/db/migrate/20210420043449_create_blockchain_trades.rb new file mode 100644 index 00000000..25507cf8 --- /dev/null +++ b/db/migrate/20210420043449_create_blockchain_trades.rb @@ -0,0 +1,11 @@ +class CreateBlockchainTrades < ActiveRecord::Migration[5.2] + def change + create_table :blockchain_trades do |t| + t.integer :project_id + t.text :description + t.float :money + + t.timestamps + end + end +end diff --git a/db/migrate/20210420072647_add_user_id_to_blockchain_trades.rb b/db/migrate/20210420072647_add_user_id_to_blockchain_trades.rb new file mode 100644 index 00000000..45e92b71 --- /dev/null +++ b/db/migrate/20210420072647_add_user_id_to_blockchain_trades.rb @@ -0,0 +1,5 @@ +class AddUserIdToBlockchainTrades < ActiveRecord::Migration[5.2] + def change + add_column :blockchain_trades, :user_id, :integer + end +end diff --git a/db/migrate/20210420131153_add_state_to_blockchain_trades.rb b/db/migrate/20210420131153_add_state_to_blockchain_trades.rb new file mode 100644 index 00000000..768dbcc6 --- /dev/null +++ b/db/migrate/20210420131153_add_state_to_blockchain_trades.rb @@ -0,0 +1,5 @@ +class AddStateToBlockchainTrades < ActiveRecord::Migration[5.2] + def change + add_column :blockchain_trades, :state, :integer + end +end diff --git a/db/migrate/20210420131244_add_user_id2_to_blockchain_trades.rb b/db/migrate/20210420131244_add_user_id2_to_blockchain_trades.rb new file mode 100644 index 00000000..7c1d3270 --- /dev/null +++ b/db/migrate/20210420131244_add_user_id2_to_blockchain_trades.rb @@ -0,0 +1,5 @@ +class AddUserId2ToBlockchainTrades < ActiveRecord::Migration[5.2] + def change + add_column :blockchain_trades, :user_id2, :integer + end +end diff --git a/db/migrate/20210421043328_add_token_num_to_blockchain_trades.rb b/db/migrate/20210421043328_add_token_num_to_blockchain_trades.rb new file mode 100644 index 00000000..1fbe90c6 --- /dev/null +++ b/db/migrate/20210421043328_add_token_num_to_blockchain_trades.rb @@ -0,0 +1,5 @@ +class AddTokenNumToBlockchainTrades < ActiveRecord::Migration[5.2] + def change + add_column :blockchain_trades, :token_num, :integer + end +end diff --git a/db/migrate/20210421081736_add_blockchain_token_num_to_issue.rb b/db/migrate/20210421081736_add_blockchain_token_num_to_issue.rb new file mode 100644 index 00000000..1391667e --- /dev/null +++ b/db/migrate/20210421081736_add_blockchain_token_num_to_issue.rb @@ -0,0 +1,5 @@ +class AddBlockchainTokenNumToIssue < ActiveRecord::Migration[5.2] + def change + add_column :issues, :blockchain_token_num, :integer + end +end diff --git a/public/react/build b/public/react/build new file mode 160000 index 00000000..f872fb6c --- /dev/null +++ b/public/react/build @@ -0,0 +1 @@ +Subproject commit f872fb6cb5507c31d48243eb905e041dad0ac764 diff --git a/spec/models/blockchain_trade_spec.rb b/spec/models/blockchain_trade_spec.rb new file mode 100644 index 00000000..9f957475 --- /dev/null +++ b/spec/models/blockchain_trade_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe BlockchainTrade, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end