806 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			806 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Ruby
		
	
	
	
class UsersController < ApplicationController
 | 
						||
  include ApplicationHelper
 | 
						||
  include Ci::DbConnectable
 | 
						||
 | 
						||
  before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard, :hovercard4proj]
 | 
						||
  before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard, :hovercard4proj]
 | 
						||
  before_action :require_login, only: %i[me sync_user_info]
 | 
						||
  before_action :connect_to_ci_db, only: [:get_user_info]
 | 
						||
  before_action :convert_image!, only: [:update, :update_image]
 | 
						||
  skip_before_action :check_sign, only: [:attachment_show]
 | 
						||
  before_action :sso_login, only: [:get_user_info]
 | 
						||
 | 
						||
  def connect_to_ci_db(options={})
 | 
						||
    if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
 | 
						||
      return
 | 
						||
    end
 | 
						||
    if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
 | 
						||
      connect_to_trustie_ci_database(options)
 | 
						||
    else
 | 
						||
      connect_to_ci_database(options)
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
  def list
 | 
						||
    scope = User.active.like(params[:search]).includes(:user_extension).order(nickname: :desc, last_login_on: :desc)
 | 
						||
    @total_count = scope.size
 | 
						||
    @users = paginate(scope)
 | 
						||
  end
 | 
						||
 | 
						||
  def show
 | 
						||
      #待办事项,现在未做
 | 
						||
      if User.current.admin? || User.current.login == @user.login 
 | 
						||
        @waiting_applied_messages = @user.applied_messages.waiting
 | 
						||
        @common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
 | 
						||
        @common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
 | 
						||
        #@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
 | 
						||
        @undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
 | 
						||
      else 
 | 
						||
        @waiting_applied_messages = AppliedMessage.none
 | 
						||
        @common_applied_transfer_projects = AppliedTransferProject.none
 | 
						||
        @common_applied_projects = AppliedProject.none
 | 
						||
        @undo_events = 0
 | 
						||
      end
 | 
						||
      #用户的组织数量
 | 
						||
      # @user_composes_count =  @user.composes.size
 | 
						||
      @user_composes_count = 0
 | 
						||
      user_organizations =  User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
 | 
						||
      @user_org_count = user_organizations.size
 | 
						||
      normal_projects = Project.members_projects(@user.id).to_sql
 | 
						||
      org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
 | 
						||
      projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
 | 
						||
      user_projects = User.current.logged? && (User.current.admin? ||  User.current.login == @user.login) ? projects : projects.visible
 | 
						||
      @projects_common_count = user_projects.common.size
 | 
						||
      @projects_mirrior_count = user_projects.mirror.size
 | 
						||
      @projects_sync_mirrior_count = user_projects.sync_mirror.size
 | 
						||
      # 为了缓存活跃用户的基本信息,后续删除
 | 
						||
      Cache::V2::OwnerCommonService.new(@user.id).read
 | 
						||
  end
 | 
						||
 | 
						||
  def action
 | 
						||
    if params[:action_id].present? && params[:action_type].present?
 | 
						||
      UserAction.create(:action_id => params[:action_id], :action_type => "#{params[:action_type]}", :user_id => User.current.id, :ip => request.remote_ip)
 | 
						||
    end
 | 
						||
    render_ok
 | 
						||
  end
 | 
						||
 | 
						||
  def watch_users
 | 
						||
    watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
 | 
						||
    if params[:search].present?
 | 
						||
      search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
 | 
						||
      watchers = watchers.where(watchable_id: search_user_ids)
 | 
						||
    end
 | 
						||
    @watchers_count = watchers.size
 | 
						||
    @watchers = paginate(watchers)
 | 
						||
  end
 | 
						||
 | 
						||
  def fan_users
 | 
						||
    watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
 | 
						||
    watchers = watchers.joins(:user).merge(User.like(params[:search]))
 | 
						||
    @watchers_count = watchers.size
 | 
						||
    @watchers = paginate(watchers)
 | 
						||
  end
 | 
						||
 | 
						||
  def contribution_perc
 | 
						||
    project_id = params[:project_id]
 | 
						||
    @project = Project.find(project_id)
 | 
						||
    user_id = params[:id]
 | 
						||
    @user = User.find(user_id)
 | 
						||
 | 
						||
    def cal_perc(count_user, count_all)
 | 
						||
      (count_user * 1.0 / (count_all + 0.000000001)).round(5)
 | 
						||
    end
 | 
						||
 | 
						||
    if @project['use_blockchain'] == true or @project['use_blockchain'] == 1
 | 
						||
      balance_user = Blockchain::BalanceQueryOneProject.call({"user_id": user_id, "project_id": project_id})
 | 
						||
      balance_all = Blockchain::RepoBasicInfo.call({"project_id": project_id})["cur_supply"]
 | 
						||
      scores = {
 | 
						||
        "final" => cal_perc(balance_user, balance_all),
 | 
						||
        "blockchain" => true
 | 
						||
      }
 | 
						||
    else
 | 
						||
      # 获取所有行为对应的项目内记录总数和个人记录数
 | 
						||
      features = {
 | 
						||
        "requirement" => {},
 | 
						||
        "development" => {},
 | 
						||
        "review" => {}
 | 
						||
      }
 | 
						||
 | 
						||
      # 1. issue创建
 | 
						||
      issues = Issue.where(project_id: project_id, issue_classify: 'issue')
 | 
						||
      issue_all = issues.count
 | 
						||
      issue_user = issues.where(author_id: user_id).count
 | 
						||
      features["requirement"] = features["requirement"].merge({"issue" => {"all" => issue_all, "perc" => cal_perc(issue_user, issue_all)}})
 | 
						||
      # 2. 里程碑创建
 | 
						||
      milestones = Version.where(project_id: project_id)
 | 
						||
      milestone_all = milestones.count
 | 
						||
      milestone_user = milestones.where(user_id: user_id).count
 | 
						||
      features["requirement"] = features["requirement"].merge({"milestone" => {"all" => milestone_all, "perc" => cal_perc(milestone_user, milestone_all)}})
 | 
						||
      # 3. issue评论
 | 
						||
      issue_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{project_id} and journalized_type='Issue' and issues.issue_classify='issue'")
 | 
						||
      issue_comment_all = issue_comments.count
 | 
						||
      issue_comment_user = issue_comments.where("journals.user_id=#{user_id}").count
 | 
						||
      features["requirement"] = features["requirement"].merge({"issue_comment" => {"all" => issue_comment_all, "perc" => cal_perc(issue_comment_user, issue_comment_all)}})
 | 
						||
      # 4. 合并请求
 | 
						||
      prs = PullRequest.where(project_id: project_id)
 | 
						||
      pr_all = prs.count
 | 
						||
      pr_user = prs.where(user_id: user_id).count
 | 
						||
      features["development"] = features["development"].merge({"pr" => {"all" => pr_all, "perc" => cal_perc(pr_user, pr_all)}})
 | 
						||
      # 5. pr评论
 | 
						||
      pr_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{project_id} and journalized_type='Issue' and issues.issue_classify='pull_request'")
 | 
						||
      pr_comment_all = pr_comments.count
 | 
						||
      pr_comment_user = pr_comments.where("journals.user_id=#{user_id}").count
 | 
						||
      features["review"] = features["review"].merge({"pr_comment" => {"all" => pr_comment_all, "perc" => cal_perc(pr_comment_user, pr_comment_all)}})
 | 
						||
      # 6. 代码行评论
 | 
						||
      line_comments = Journal.joins("INNER JOIN pull_requests on journals.journalized_id=pull_requests.id").where("pull_requests.project_id=#{project_id} and journalized_type='PullRequest'")
 | 
						||
      line_comment_all = line_comments.count
 | 
						||
      line_comment_user = line_comments.where("journals.user_id=#{user_id}").count
 | 
						||
      features["review"] = features["review"].merge({"line_comment" => {"all" => line_comment_all, "perc" => cal_perc(line_comment_user, line_comment_all)}})
 | 
						||
      # 7. 代码行、commit贡献统计
 | 
						||
      code_contributions = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: nil})
 | 
						||
      commit_all = code_contributions["commit_count"]
 | 
						||
      addition_all = code_contributions["additions"]
 | 
						||
      deletion_all = code_contributions["deletions"]
 | 
						||
 | 
						||
      commit_user = 0
 | 
						||
      addition_user = 0
 | 
						||
      deletion_user = 0
 | 
						||
      code_contributions["authors"].each do |author|
 | 
						||
        if author["name"] == @user.login
 | 
						||
          commit_user = author["commits"]
 | 
						||
          addition_user = author["additions"]
 | 
						||
          deletion_user = author["deletions"]
 | 
						||
        end
 | 
						||
      end
 | 
						||
 | 
						||
      features["development"] = features["development"].merge({"commit" => {"all" => commit_all, "perc" => cal_perc(commit_user, commit_all)}})
 | 
						||
      features["development"] = features["development"].merge({"addition" => {"all" => addition_all, "perc" => cal_perc(addition_user, addition_all)}})
 | 
						||
      features["development"] = features["development"].merge({"deletion" => {"all" => deletion_all, "perc" => cal_perc(deletion_user, deletion_all)}})
 | 
						||
 | 
						||
      def cal_weight(features)
 | 
						||
        weights = {} # 计算每一项的权重
 | 
						||
        categories = []
 | 
						||
        features.each do |key, _|
 | 
						||
          categories << key
 | 
						||
          weights[key] = Hash.new
 | 
						||
        end
 | 
						||
        count_all = 0
 | 
						||
        counts = {}
 | 
						||
        categories.each do |category|
 | 
						||
          count_1 = 0
 | 
						||
          features[category].each do |_, value|
 | 
						||
            count_1 += value["all"]
 | 
						||
          end
 | 
						||
          count_all += count_1
 | 
						||
          counts[category] = count_1
 | 
						||
          features[category].each do |key, value|
 | 
						||
            weight = cal_perc(value["all"], count_1)
 | 
						||
            weights[category] = weights[category].merge({key => weight})
 | 
						||
          end
 | 
						||
        end
 | 
						||
        categories.each do |category|
 | 
						||
          weight = cal_perc(counts[category], count_all)
 | 
						||
          weights[category] = weights[category].merge({"category_weight" => weight})
 | 
						||
        end
 | 
						||
        return weights
 | 
						||
      end
 | 
						||
 | 
						||
      weights_categories = cal_weight(features)
 | 
						||
      scores = {
 | 
						||
        "final" => 0.0,
 | 
						||
        "blockchain" => false
 | 
						||
      }
 | 
						||
      features.each do |category, value_1|
 | 
						||
        category_score = 0.0
 | 
						||
        value_1.each do |action, value_2|
 | 
						||
          category_score += weights_categories[category][action] * value_2["perc"]
 | 
						||
        end
 | 
						||
        scores["final"] += weights_categories[category]["category_weight"] * category_score.round(4)
 | 
						||
        scores = scores.merge({category => category_score.round(4)})
 | 
						||
      end
 | 
						||
    end
 | 
						||
    render json: { scores: scores }
 | 
						||
  end
 | 
						||
 | 
						||
  def hovercard
 | 
						||
  end
 | 
						||
 | 
						||
  # author: zxh, 查询贡献者的贡献度
 | 
						||
  def hovercard4proj
 | 
						||
  end
 | 
						||
 | 
						||
  def update
 | 
						||
    return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id]) 
 | 
						||
    return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
 | 
						||
    if user_params[:nickname].present?
 | 
						||
      keywords = user_params[:nickname].to_s.each_char.select { |c| c.bytes.first < 240 }.join('')
 | 
						||
      return normal_status(-1, "昵称中包含关键词:#{keywords},请重新命名") if ReversedKeyword.check_exists?(keywords)
 | 
						||
    end
 | 
						||
    Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
 | 
						||
    @user.attributes = user_params.except(:image)
 | 
						||
    unless @user.save
 | 
						||
      render_error(-1, @user.errors.full_messages.join(", "))
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
  def update_image
 | 
						||
    return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
 | 
						||
    return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
 | 
						||
 | 
						||
    Util.write_file(@image, avatar_path(@user))
 | 
						||
    return render_ok({message: '头像修改成功'})
 | 
						||
  rescue Exception => e
 | 
						||
    uid_logger_error(e.message)
 | 
						||
    render_error(-1, '头像修改失败!')
 | 
						||
  end
 | 
						||
 | 
						||
  def get_image
 | 
						||
    return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
 | 
						||
    # return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
 | 
						||
 | 
						||
    redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
 | 
						||
  end
 | 
						||
 | 
						||
  def me
 | 
						||
    @user = current_user
 | 
						||
  end
 | 
						||
 | 
						||
  # cloudIDE saas定制
 | 
						||
  def info
 | 
						||
    @code = 1001
 | 
						||
    @message = "用户不存在"
 | 
						||
    if params[:token].present?
 | 
						||
      @user = User.try_to_autologin(params[:token])
 | 
						||
      if @user.present?
 | 
						||
        @code = 1000
 | 
						||
        @message = "success"
 | 
						||
      end
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
  # 贴吧获取用户信接口
 | 
						||
  def get_user_info
 | 
						||
    begin
 | 
						||
      @user = current_user
 | 
						||
      begin
 | 
						||
        result = Notice::Read::CountService.call(current_user.id)
 | 
						||
        @message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
 | 
						||
      rescue 
 | 
						||
        @message_unread_total = 0
 | 
						||
      end
 | 
						||
      # TODO 等消息上线再打开注释
 | 
						||
      #@tidding_count = unviewed_tiddings(current_user) if current_user.present?
 | 
						||
    rescue Exception => e
 | 
						||
      uid_logger_error(e.message)
 | 
						||
      missing_template
 | 
						||
    end
 | 
						||
 | 
						||
  end
 | 
						||
 | 
						||
  def attachment_show
 | 
						||
    file_name = params[:file_name]
 | 
						||
    path = params[:path] || file_storage_directory
 | 
						||
    send_file "#{path}/#{file_name}", :filename => "#{file_name}",
 | 
						||
              :type => 'game',
 | 
						||
              :disposition => 'attachment' #inline can open in browser
 | 
						||
  end
 | 
						||
 | 
						||
  def html_show
 | 
						||
    @contents = File.read("#{params[:path]}")
 | 
						||
    respond_to do |format|
 | 
						||
      format.html {render :layout => false}
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
  # Redo: 消息总数缓存
 | 
						||
  def get_navigation_info
 | 
						||
    # @old_domain = edu_setting('old_edu_host')
 | 
						||
    # @user = current_user
 | 
						||
    # # 新消息数
 | 
						||
    # @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
 | 
						||
    #
 | 
						||
    # @user_url = "/users/#{@user.login}"
 | 
						||
    # @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
 | 
						||
    # @auth =  User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
 | 
						||
  end
 | 
						||
 | 
						||
  # 用户回复功能
 | 
						||
  def reply_message
 | 
						||
    message = JournalsForMessage.new(reply_message_params)
 | 
						||
    message.user_id = current_user.id
 | 
						||
    message.save!
 | 
						||
 | 
						||
    render_ok(id: message.id)
 | 
						||
  end
 | 
						||
 | 
						||
  # 搜索用户具有管理员角色的项目
 | 
						||
  def search_user_projects
 | 
						||
    projects = Project.where.not(status: 9)
 | 
						||
 | 
						||
    projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
 | 
						||
    projects = projects.where(members: { user_id: current_user.id })
 | 
						||
 | 
						||
    search = params[:search].to_s.strip
 | 
						||
    projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
 | 
						||
 | 
						||
    @projects = projects.select(:id, :name)
 | 
						||
  end
 | 
						||
 | 
						||
  #TODO 个人主页信息,forge上弃用-hs, 0602
 | 
						||
  def homepage_info
 | 
						||
    #待办事项,现在未做
 | 
						||
    @undo_events = 10
 | 
						||
    #用户的组织数量
 | 
						||
    # @user_composes_count =  @user.composes.size
 | 
						||
    @user_composes_count = 10
 | 
						||
  end
 | 
						||
 | 
						||
  def brief_introduction
 | 
						||
    content = params[:content].to_s.strip
 | 
						||
 | 
						||
    current_user.user_extension.update!(brief_introduction: content)
 | 
						||
 | 
						||
    render_ok
 | 
						||
  end
 | 
						||
 | 
						||
  def attendance
 | 
						||
    attendance = Users::AttendanceService.call(current_user)
 | 
						||
    render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
 | 
						||
  rescue Users::AttendanceService::Error => ex
 | 
						||
    render_error(ex.message)
 | 
						||
  end
 | 
						||
 | 
						||
  # 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
 | 
						||
  def sync_token
 | 
						||
    return render_error('未找相关用户!')  unless @user
 | 
						||
 | 
						||
    token = Token.get_or_create_permanent_login_token(@user, 'autologin')
 | 
						||
    token.update_column(:value, params[:token])
 | 
						||
    render_ok
 | 
						||
  end
 | 
						||
 | 
						||
  def trustie_related_projects
 | 
						||
    projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
 | 
						||
    projects_json = []
 | 
						||
    domain_url = EduSetting.get('host_name')
 | 
						||
    if projects.present?
 | 
						||
      projects.each do |p|
 | 
						||
        project_url = "/#{p.owner.login}/#{p.identifier}"
 | 
						||
        pj = {
 | 
						||
          id: p.id,
 | 
						||
          name: p.name,
 | 
						||
          is_public: p.is_public,
 | 
						||
          updated_on: p.updated_on.strftime("%Y-%m-%d"),
 | 
						||
          status: p.status,
 | 
						||
          is_member: p.member?(current_user.try(:id)),
 | 
						||
          owner: {
 | 
						||
            name: p.owner.try(:show_real_name),
 | 
						||
            login: p.owner.login
 | 
						||
          },
 | 
						||
          members_count: p&.members.size,
 | 
						||
          issues_count: p.issues_count - p.pull_requests_count,
 | 
						||
          commits_count: p&.project_score&.changeset_num.to_i,
 | 
						||
          http_url: domain_url + project_url,
 | 
						||
          http_collaborator_url: domain_url + project_url + "/setting/collaborator",
 | 
						||
          http_issues_url: domain_url + project_url + "/issues",
 | 
						||
          http_commits_url: domain_url + project_url + "/commits",
 | 
						||
          project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
 | 
						||
        }
 | 
						||
        projects_json.push(pj)
 | 
						||
      end
 | 
						||
    end
 | 
						||
    Rails.logger.info("==========projects_json========+########{projects_json}")
 | 
						||
    render json: { projects: projects_json.present? ? projects_json : {} }
 | 
						||
  end
 | 
						||
 | 
						||
  def trustie_projects
 | 
						||
    user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
 | 
						||
    projects = Project.visible
 | 
						||
 | 
						||
    projects = projects.joins(:members).where(members: { user_id: user_id })
 | 
						||
 | 
						||
    search = params[:search].to_s.strip
 | 
						||
    projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
 | 
						||
 | 
						||
    projects = projects.select(:id, :name).limit(10).as_json
 | 
						||
    render json: { projects: projects }
 | 
						||
  end
 | 
						||
 | 
						||
  def projects
 | 
						||
    is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
 | 
						||
    scope, @home_top_ids = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
 | 
						||
    @total_count = scope.size
 | 
						||
    @projects = kaminari_unlimit_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)
 | 
						||
    is_current_admin_user = true
 | 
						||
    results = Blockchain::BalanceQuery.call(params, is_current_admin_user)
 | 
						||
    if results[:status] == 0
 | 
						||
      @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 }
 | 
						||
  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)
 | 
						||
    is_current_admin_user = true
 | 
						||
    if is_current_admin_user
 | 
						||
      owner = User.find_by(login: params['owner_login'])
 | 
						||
      if owner.nil?
 | 
						||
        normal_status(-1, "创建者无法找到")
 | 
						||
      else
 | 
						||
        p = Project.find_by(user_id: owner.id, identifier: params['project_identifier'])
 | 
						||
        balance = Blockchain::BalanceQueryOneProject.call({"user_id": params['user_id'].to_i, "project_id": p.id.to_i})
 | 
						||
        render json: { status: 0, balance: balance}
 | 
						||
      end
 | 
						||
    else
 | 
						||
      normal_status(-1, "缺少权限")
 | 
						||
    end
 | 
						||
 | 
						||
  end
 | 
						||
 | 
						||
 | 
						||
  def blockchain_transfer
 | 
						||
    #is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['payer_id'].to_i)
 | 
						||
    is_current_admin_user = true
 | 
						||
 | 
						||
    if is_current_admin_user
 | 
						||
      Blockchain::TransferService.call(params)
 | 
						||
      render json: {status: 2} # 重新查询余额
 | 
						||
    else
 | 
						||
      normal_status(-1, "缺少权限")
 | 
						||
    end
 | 
						||
  rescue Exception => e
 | 
						||
    normal_status(-1, e.to_s)
 | 
						||
  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)
 | 
						||
  # #   is_current_admin_user = true
 | 
						||
  # #   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
 | 
						||
  # #       normal_status(-1, "创建交易失败")
 | 
						||
  # #     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
 | 
						||
  # #     normal_status(-1, "缺少权限")
 | 
						||
  # #   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)
 | 
						||
  # #   is_current_admin_user = true
 | 
						||
  # #   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
 | 
						||
  # #     normal_status(-1, "缺少权限")
 | 
						||
  # #   end
 | 
						||
  # # end
 | 
						||
  #
 | 
						||
  #
 | 
						||
  # def blockchain_verify_trade
 | 
						||
  #   #is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
 | 
						||
  #   is_current_admin_user = true
 | 
						||
  #   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
 | 
						||
  #     normal_status(-1, "缺少权限")
 | 
						||
  #   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)
 | 
						||
  #   is_current_admin_user = true
 | 
						||
  #   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
 | 
						||
  #     normal_status(-1, "缺少权限")
 | 
						||
  #   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)
 | 
						||
  #   is_current_admin_user = true
 | 
						||
  #   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
 | 
						||
  #     normal_status(-1, "缺少权限")
 | 
						||
  #   end
 | 
						||
  # end
 | 
						||
 | 
						||
 | 
						||
  def blockchain_get_issue_token_num
 | 
						||
    issue_id = params["issue_id"]['orderId'].to_i
 | 
						||
    issue = Issue.find_by(id: issue_id)
 | 
						||
    project = Project.find(issue.project_id)
 | 
						||
    if project[:use_blockchain]
 | 
						||
      render json: {"blockchain_token_num": issue.blockchain_token_num}
 | 
						||
    else
 | 
						||
      render json: {"blockchain_token_num": -1} # 未使用blockchain
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
 | 
						||
  def blockchain_get_unclosed_issue_list
 | 
						||
    ownername = params["ownername"]
 | 
						||
    identifier = params["reponame"]
 | 
						||
    owner = User.find_by(login: ownername)
 | 
						||
    project = Project.find_by(user_id: owner.id, identifier: identifier)
 | 
						||
    unclosed_issues = Issue.where(project_id: project.id, issue_classify: "issue").where.not(status_id: 5)
 | 
						||
    results = []
 | 
						||
    unclosed_issues.each do |i|
 | 
						||
      results << [i.id, i.subject]
 | 
						||
    end
 | 
						||
    render json: {unclosed_issues: results}
 | 
						||
  end
 | 
						||
 | 
						||
  # TODO 其他平台登录时同步修改gitea平台对应用户的密码
 | 
						||
  # 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
 | 
						||
  def sync_gitea_pwd
 | 
						||
    return render_error("未找到相关的用户") if @user.blank?
 | 
						||
 | 
						||
    flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
 | 
						||
    flag ? render_ok : render_error('同步失败!')
 | 
						||
  end
 | 
						||
 | 
						||
  # TODO
 | 
						||
  # 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
 | 
						||
  def sync_salt
 | 
						||
    user = User.find_by_login params[:login]
 | 
						||
    return if user.blank?
 | 
						||
    user.update_column(:salt, params[:salt])
 | 
						||
    render_ok
 | 
						||
  end
 | 
						||
 | 
						||
  def sync_user_info
 | 
						||
    user = User.find_by_login params[:login]
 | 
						||
    return render_forbidden unless user === current_user
 | 
						||
 | 
						||
    sync_params = {
 | 
						||
      email: params[:email],
 | 
						||
      password: params[:password]
 | 
						||
    }
 | 
						||
 | 
						||
    Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
 | 
						||
 | 
						||
    interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
 | 
						||
    if interactor.success?
 | 
						||
      user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
 | 
						||
      render_ok
 | 
						||
    else
 | 
						||
      render_error(interactor.error)
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
  def email_search
 | 
						||
    return render_error('请输入email') if params[:email].blank?
 | 
						||
    @user = User.find_by(mail: params[:email])
 | 
						||
  end
 | 
						||
 | 
						||
  #根据login获取用户信息
 | 
						||
  def get_user_info_by_login
 | 
						||
    private_token = "hriEn3UwXfJs3PmyXnSH"
 | 
						||
    sign = Digest::MD5.hexdigest("#{private_token}:#{params[:login]}")
 | 
						||
    tip_exception(401, '401 Unauthorized')  unless params[:sign].to_s == sign
 | 
						||
    user = User.find_by_login params[:login]
 | 
						||
    render_ok(data: {username: user.real_name, school: user.custom_department, login: user.login, phone: user.phone, mail: user.mail})
 | 
						||
  end
 | 
						||
 | 
						||
  private
 | 
						||
  def load_user
 | 
						||
    @user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
 | 
						||
    clear_user_cookie unless @user.present?
 | 
						||
  end
 | 
						||
 | 
						||
  def user_params
 | 
						||
    params.require(:user).permit(:nickname, :image,
 | 
						||
                                  user_extension_attributes: [
 | 
						||
                                  :gender, :location, :location_city,
 | 
						||
                                  :occupation, :technical_title,
 | 
						||
                                  :school_id, :department_id, :province, :city,
 | 
						||
                                  :custom_department, :identity, :student_id, :description,
 | 
						||
                                  :show_super_description, :super_description,
 | 
						||
                                  :show_email, :show_location, :show_department]
 | 
						||
                                )
 | 
						||
  end
 | 
						||
 | 
						||
  def reply_message_params
 | 
						||
    normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
 | 
						||
        params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
 | 
						||
    params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
 | 
						||
  end
 | 
						||
 | 
						||
  def check_user_exist
 | 
						||
    return if @user.present?
 | 
						||
    render_not_found
 | 
						||
  end
 | 
						||
 | 
						||
  def sso_login
 | 
						||
    if params[:login].present? && !current_user.logged? && params[:websiteName].present? && request.referer.to_s.include?("gitlink.org.cn")
 | 
						||
      user = User.where("login = ?", "#{params[:login].presence}").first
 | 
						||
      # 已同步注册,直接登录
 | 
						||
      if user.present?
 | 
						||
        successful_authentication(user)
 | 
						||
      else
 | 
						||
        autologin_register_by_educoder(params[:login].presence)
 | 
						||
      end
 | 
						||
    end
 | 
						||
  end
 | 
						||
 | 
						||
  # 通过login参数查询头歌账号信息,注册并登录
 | 
						||
  def autologin_register_by_educoder(edu_login)
 | 
						||
    req_params = { "login" => "#{edu_login}", "private_token" => "hriEn3UwXfJs3PmyXnqQ" }
 | 
						||
    api_url=  "https://data.educoder.net"
 | 
						||
    client = Faraday.new(url: api_url)
 | 
						||
    response = client.public_send("get", "/api/sources/get_user_info_by_login", req_params)
 | 
						||
    result = JSON.parse(response.body)
 | 
						||
    #查询
 | 
						||
    return nil if result["status"].to_s != "0"
 | 
						||
 | 
						||
    # login 邮箱 手机号 姓名 学校/单位
 | 
						||
    user_info = result["data"]
 | 
						||
    Rails.logger.info("user_info====== #{user_info}")
 | 
						||
    login = user_info["login"]
 | 
						||
    email = user_info["mail"]
 | 
						||
    phone = user_info["phone"]
 | 
						||
    real_name = user_info["username"]
 | 
						||
    department_name = user_info["school"]
 | 
						||
    password = "12345678"
 | 
						||
 | 
						||
    # 没有用户时,新建用户并登录
 | 
						||
    user = phone.present? ? User.find_by(phone: phone) : nil
 | 
						||
    user = User.where("login = ?  or phone = ? or mail = ? ", "#{login}", phone, email).first if user.nil?
 | 
						||
    if user.present?
 | 
						||
      # 手机号先记录,后续用
 | 
						||
      user.update_column(:phone, "#{phone}") if phone.present? && user.phone.blank?
 | 
						||
    else
 | 
						||
      ActiveRecord::Base.transaction do
 | 
						||
        email = "#{login}@gitlink.org.cn" if email.blank?
 | 
						||
        user_params = { status: 1, type: 'User', login: "#{login}", lastname: "#{real_name}", mail: "#{email}",
 | 
						||
                        nickname: "#{real_name}", professional_certification: 0, certification: 0, grade: 0,
 | 
						||
                        password: "#{password}", phone: "#{phone}", profile_completed: 1 }
 | 
						||
        user = User.create!(user_params)
 | 
						||
        UserExtension.create!(user_id: user.id, gender: 1, custom_department: "#{department_name}")
 | 
						||
        interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: password})
 | 
						||
        if interactor.success?
 | 
						||
          gitea_user = interactor.result
 | 
						||
          Rails.logger.info("Gitea::RegisterInteractor.call result====== #{gitea_user}")
 | 
						||
          result = Gitea::User::GenerateTokenService.call(login, password)
 | 
						||
          user.gitea_token = result['sha1']
 | 
						||
          user.gitea_uid = gitea_user[:body]['id']
 | 
						||
          user.save!
 | 
						||
        else
 | 
						||
          Rails.logger.info("Gitea::RegisterInteractor.call error====== #{interactor.error}")
 | 
						||
        end
 | 
						||
      end
 | 
						||
    end
 | 
						||
    successful_authentication(user) if user.present?
 | 
						||
  end
 | 
						||
 | 
						||
end
 |