297 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Ruby
		
	
	
	
class ProjectsController < ApplicationController
 | 
						|
  include ApplicationHelper
 | 
						|
  include OperateProjectAbilityAble
 | 
						|
  include ProjectsHelper
 | 
						|
  include Acceleratorable
 | 
						|
 | 
						|
  before_action :require_login, except: %i[index branches branches_slice group_type_list simple show fork_users praise_users watch_users recommend banner_recommend about menu_list]
 | 
						|
  before_action :require_profile_completed, only: [:create, :migrate]
 | 
						|
  before_action :load_repository, except: %i[index group_type_list migrate create recommend banner_recommend]
 | 
						|
  before_action :authorizate_user_can_edit_project!, only: %i[update]
 | 
						|
  before_action :project_public?, only: %i[fork_users praise_users watch_users]
 | 
						|
 | 
						|
  def menu_list
 | 
						|
    menu = []
 | 
						|
 | 
						|
    user_is_admin = current_user.admin? || @project.manager?(current_user)
 | 
						|
 | 
						|
    menu.append(menu_hash_by_name("home"))
 | 
						|
    menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
 | 
						|
    menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
 | 
						|
    menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge?
 | 
						|
    menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
 | 
						|
    menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
 | 
						|
    menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
 | 
						|
    menu.append(menu_hash_by_name("services")) if @project.has_menu_permission("services") && @project.forge? && (current_user.admin? || @project.member?(current_user.id))
 | 
						|
    menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
 | 
						|
    menu.append(menu_hash_by_name("activity"))
 | 
						|
    menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
 | 
						|
    menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
 | 
						|
 | 
						|
    render json: menu
 | 
						|
  end
 | 
						|
 | 
						|
  def index
 | 
						|
    scope = current_user.logged? ? Projects::ListQuery.call(params, current_user.id) : Projects::ListQuery.call(params)
 | 
						|
 | 
						|
    @projects = kaminari_paginate(scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units))
 | 
						|
    # @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
 | 
						|
 | 
						|
    category_id = params[:category_id]
 | 
						|
    @total_count =
 | 
						|
      if category_id.blank? && params[:search].blank?
 | 
						|
        # 默认查询时count性能问题处理
 | 
						|
        ProjectCategory.sum("projects_count") - Project.visible.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id").where("organization_extensions.visibility =2").count
 | 
						|
      elsif params[:search].present?
 | 
						|
        @projects.total_count
 | 
						|
      else
 | 
						|
       cate = ProjectCategory.find_by(id: category_id)
 | 
						|
       cate&.projects_count || 0
 | 
						|
      end
 | 
						|
  end
 | 
						|
 | 
						|
  def create
 | 
						|
    ActiveRecord::Base.transaction do
 | 
						|
      Projects::CreateForm.new(project_params).validate!
 | 
						|
      @project = Projects::CreateService.new(current_user, project_params).call
 | 
						|
      OpenProjectDevOpsJob.set(wait: 5.seconds).perform_later(@project&.id, current_user.id)
 | 
						|
    end
 | 
						|
  rescue Exception => e
 | 
						|
    uid_logger_error(e.message)
 | 
						|
    tip_exception(e.message)
 | 
						|
  end
 | 
						|
 | 
						|
  def migrate
 | 
						|
    Projects::MigrateForm.new(mirror_params).validate!
 | 
						|
 | 
						|
    @project = 
 | 
						|
      if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
 | 
						|
        source_clone_url = mirror_params[:clone_addr]
 | 
						|
        uid_logger("########## 已动加速器 ##########")
 | 
						|
        result = Gitea::Accelerator::MigrateService.call(mirror_params)
 | 
						|
        if result[:status] == :success
 | 
						|
          Rails.logger.info "########## 加速镜像成功 ########## "
 | 
						|
          Projects::MigrateService.call(current_user, 
 | 
						|
            mirror_params.merge(source_clone_url: source_clone_url, 
 | 
						|
              clone_addr: accelerator_url(mirror_params[:repository_name])))
 | 
						|
        else
 | 
						|
          Projects::MigrateService.call(current_user, mirror_params)
 | 
						|
        end
 | 
						|
      elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
 | 
						|
        source_clone_url = mirror_params[:clone_addr]
 | 
						|
        clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
 | 
						|
        uid_logger("########## 更改clone_addr ##########")
 | 
						|
        Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
 | 
						|
      else
 | 
						|
        Projects::MigrateService.call(current_user, mirror_params)
 | 
						|
      end
 | 
						|
  rescue Exception => e
 | 
						|
    uid_logger_error(e.message)
 | 
						|
    tip_exception(e.message)
 | 
						|
  end
 | 
						|
 | 
						|
  def branches
 | 
						|
    return @branches = [] unless @project.forge?
 | 
						|
 | 
						|
    # result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
 | 
						|
    result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name])
 | 
						|
    @branches =  result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
 | 
						|
  end
 | 
						|
 | 
						|
  def branches_slice
 | 
						|
    return @branches = [] unless @project.forge?
 | 
						|
 | 
						|
    slice_result = Gitea::Repository::Branches::ListSliceService.call(@owner, @project.identifier)
 | 
						|
    @branches_slice = slice_result.is_a?(Hash) && slice_result.key?(:status) ? [] : slice_result
 | 
						|
  end
 | 
						|
 | 
						|
  def group_type_list
 | 
						|
    project_statics = ProjectStatistic.first
 | 
						|
 | 
						|
    @project_statics_list = [
 | 
						|
      {
 | 
						|
        project_type: 'common',
 | 
						|
        name: '开源托管项目',
 | 
						|
        projects_count: project_statics&.common_projects_count || 0
 | 
						|
      },
 | 
						|
      {
 | 
						|
        project_type: 'mirror',
 | 
						|
        name: '开源镜像项目',
 | 
						|
        projects_count: project_statics&.mirror_projects_count || 0
 | 
						|
      }
 | 
						|
    ]
 | 
						|
 | 
						|
    # projects = Project.no_anomory_projects.visible
 | 
						|
    # @project_group_list = projects.group(:project_type).size
 | 
						|
  end
 | 
						|
 | 
						|
  def update
 | 
						|
    ActiveRecord::Base.transaction do
 | 
						|
      # TODO:
 | 
						|
      # 临时特殊处理修改website、lesson_url操作方法
 | 
						|
      if project_params.has_key?("website") 
 | 
						|
        @project.update(project_params)
 | 
						|
      elsif project_params.has_key?("default_branch")
 | 
						|
        @project.update(project_params)
 | 
						|
        gitea_params = {
 | 
						|
          default_branch: @project.default_branch
 | 
						|
        }
 | 
						|
        Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
 | 
						|
      else
 | 
						|
        validate_params = project_params.slice(:name, :description, 
 | 
						|
          :project_category_id, :project_language_id, :private, :identifier)
 | 
						|
  
 | 
						|
        Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
 | 
						|
  
 | 
						|
        private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
 | 
						|
 | 
						|
        new_project_params = project_params.except(:private).merge(is_public: !private)
 | 
						|
        @project.update_attributes!(new_project_params)
 | 
						|
        @project.forked_projects.update_all(is_public: @project.is_public)
 | 
						|
        gitea_params = {
 | 
						|
          private: private,
 | 
						|
          default_branch: @project.default_branch,
 | 
						|
          website: @project.website,
 | 
						|
          name: @project.identifier
 | 
						|
        }
 | 
						|
        gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
 | 
						|
        @project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
 | 
						|
        # 更新对应所属分类下的项目数量(私有)
 | 
						|
        before_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][0] : @project.is_public
 | 
						|
        after_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][1] : @project.is_public
 | 
						|
        before_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][0] : @project.project_category_id
 | 
						|
        after_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][1] : @project.project_category_id
 | 
						|
        before_pc = ProjectCategory.find_by_id(before_pc_id)
 | 
						|
        after_pc = ProjectCategory.find_by_id(after_pc_id)
 | 
						|
        before_pc.decrement!(:private_projects_count, 1) if before_pc.present? && !before_is_public
 | 
						|
        after_pc.increment!(:private_projects_count, 1) if after_pc.present? && !after_is_public
 | 
						|
      end
 | 
						|
      SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
 | 
						|
    end
 | 
						|
  rescue Exception => e
 | 
						|
    uid_logger_error(e.message)
 | 
						|
    tip_exception(e.message)
 | 
						|
  end
 | 
						|
 | 
						|
  def show
 | 
						|
  end
 | 
						|
 | 
						|
  def destroy
 | 
						|
    if current_user.admin? || @project.manager?(current_user)
 | 
						|
      ActiveRecord::Base.transaction do
 | 
						|
        Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
 | 
						|
        @project.destroy!
 | 
						|
        @project.forked_projects.update_all(forked_from_project_id: nil)
 | 
						|
        # 如果该项目有所属的项目分类以及为私有项目,需要更新对应数量
 | 
						|
        @project.project_category.decrement!(:private_projects_count, 1) if @project.project_category.present? && !@project.is_public
 | 
						|
        render_ok
 | 
						|
      end
 | 
						|
    else
 | 
						|
      render_forbidden('你没有权限操作')
 | 
						|
    end
 | 
						|
  rescue Exception => e
 | 
						|
    uid_logger_error(e.message)
 | 
						|
    tip_exception(e.message)
 | 
						|
  end
 | 
						|
 | 
						|
  def quit
 | 
						|
    user_is_admin = current_user.admin? || @project.manager?(current_user)
 | 
						|
    if !user_is_admin && @project.member(current_user.id) && @project.forge? 
 | 
						|
      ActiveRecord::Base.transaction do
 | 
						|
        Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
 | 
						|
        SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
 | 
						|
        render_ok
 | 
						|
      end
 | 
						|
    else 
 | 
						|
      render_forbidden('你不能退出该仓库')
 | 
						|
    end
 | 
						|
  rescue Exception => e
 | 
						|
    uid_logger_error(e.message)
 | 
						|
    tip_exception(e.message)
 | 
						|
  end
 | 
						|
 | 
						|
  def watch_users
 | 
						|
    watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
 | 
						|
    @watchers_count = watchers.size
 | 
						|
    @watchers = paginate(watchers)
 | 
						|
  end
 | 
						|
 | 
						|
  def praise_users
 | 
						|
    praises = @project.praise_treads.includes(:user).order("praise_treads.created_at desc").distinct
 | 
						|
    @praises_count = praises.size
 | 
						|
    @praises = paginate(praises)
 | 
						|
  end
 | 
						|
 | 
						|
  def fork_users
 | 
						|
    fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct
 | 
						|
    @forks_count = fork_users.size
 | 
						|
    @fork_users = paginate(fork_users)
 | 
						|
  end
 | 
						|
 | 
						|
  def simple
 | 
						|
    # 为了缓存活跃项目的基本信息,后续删除
 | 
						|
    Cache::V2::ProjectCommonService.new(@project.id).read
 | 
						|
    json_response(@project, current_user)
 | 
						|
  end
 | 
						|
 | 
						|
  def recommend
 | 
						|
    @projects = Project.recommend.includes(:repository, :project_category, :owner).order(visits: :desc)
 | 
						|
  end
 | 
						|
 | 
						|
  def banner_recommend
 | 
						|
    @projects = Project.recommend.where.not(recommend_index: 0).includes(:project_category, :owner, :project_language).order(recommend_index: :desc)
 | 
						|
  end
 | 
						|
 | 
						|
  def about
 | 
						|
    @project_detail = @project.project_detail
 | 
						|
    @attachments = Array(@project_detail&.attachments) if request.get?
 | 
						|
    ActiveRecord::Base.transaction do
 | 
						|
      if request.post?
 | 
						|
        require_login
 | 
						|
        authorizate_user_can_edit_project!
 | 
						|
        unless @project_detail.present?
 | 
						|
          @project_detail = ProjectDetail.new(
 | 
						|
            content: params[:content],
 | 
						|
            project_id: @project.id)
 | 
						|
        else
 | 
						|
          @project_detail.content = params[:content]
 | 
						|
        end
 | 
						|
        if @project_detail.save!
 | 
						|
          attachment_ids = Array(params[:attachment_ids])
 | 
						|
          logger.info "=============> #{Array(params[:attachment_ids])}"
 | 
						|
          @attachments =  Attachment.where(id: attachment_ids)
 | 
						|
          @attachments.update_all(
 | 
						|
            container_id: @project_detail.id,
 | 
						|
            container_type: @project_detail.model_name.name,
 | 
						|
            author_id: current_user.id,
 | 
						|
            description: "")
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
 | 
						|
  private
 | 
						|
  def project_params
 | 
						|
    params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, :identifier,
 | 
						|
                  :project_category_id, :project_language_id, :license_id, :ignore_id, :private,
 | 
						|
                  :blockchain, :blockchain_token_all, :blockchain_init_token)
 | 
						|
  end
 | 
						|
 | 
						|
  def mirror_params
 | 
						|
    params.permit(:user_id, :name, :description, :repository_name, :is_mirror, :auth_username,
 | 
						|
                  :auth_password, :project_category_id, :project_language_id, :clone_addr, :private)
 | 
						|
  end
 | 
						|
 | 
						|
  def project_public?
 | 
						|
    return if @project.is_public?
 | 
						|
 | 
						|
    if current_user
 | 
						|
      return if current_user.admin? || @project.member?(current_user.id)
 | 
						|
      render_forbidden('你没有权限访问.')
 | 
						|
    else
 | 
						|
      render_unauthorized('你还未登录.')
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |