fix: merge from pre_trustie_server

This commit is contained in:
yystopf 2022-04-01 18:35:08 +08:00
commit 0154115f6b
37 changed files with 1059 additions and 648 deletions

View File

@ -217,7 +217,7 @@ class AttachmentsController < ApplicationController
if @file.container && current_user.logged? if @file.container && current_user.logged?
if @file.container.is_a?(Issue) if @file.container.is_a?(Issue)
course = @file.container.project course = @file.container.project
candown = course.member?(current_user) candown = course.member?(current_user) || course.is_public
elsif @file.container.is_a?(Journal) elsif @file.container.is_a?(Journal)
course = @file.container.issue.project course = @file.container.issue.project
candown = course.member?(current_user) candown = course.member?(current_user)

View File

@ -16,6 +16,7 @@ class CompareController < ApplicationController
if @base.blank? || @head.blank? if @base.blank? || @head.blank?
return -2, "请选择分支" return -2, "请选择分支"
else else
return -2, "目标仓库未开启合并请求PR功能" unless @project.has_menu_permission("pulls")
if @head.include?(":") if @head.include?(":")
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
return -2, "请选择正确的仓库" unless fork_project.present? return -2, "请选择正确的仓库" unless fork_project.present?
@ -50,6 +51,6 @@ class CompareController < ApplicationController
end end
def gitea_compare(base, head) def gitea_compare(base, head)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token) Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
end end
end end

View File

@ -24,7 +24,7 @@ class IssuesController < ApplicationController
@filter_issues = @all_issues @filter_issues = @all_issues
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD @filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING @filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present? @filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED) @open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED) @close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue") scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")

View File

@ -5,7 +5,11 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
def index def index
@organization_users = @organization.organization_users.includes(:user) @organization_users = @organization.organization_users.includes(:user)
search = params[:search].to_s.downcase search = params[:search].to_s.downcase
@organization_users = @organization_users.joins(:user).merge(User.like(search)) user_condition_users = User.like(search).to_sql
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
@organization_users = @organization_users.where(user_id: users).distinct
@organization_users = kaminari_paginate(@organization_users) @organization_users = kaminari_paginate(@organization_users)
end end

View File

@ -135,7 +135,7 @@ class ProjectsController < ApplicationController
validate_params = project_params.slice(:name, :description, validate_params = project_params.slice(:name, :description,
:project_category_id, :project_language_id, :private, :identifier) :project_category_id, :project_language_id, :private, :identifier)
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate! 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 private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false

View File

@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
before_action :require_login, except: [:index, :show, :files, :commits] before_action :require_login, except: [:index, :show, :files, :commits]
before_action :require_profile_completed, only: [:create] before_action :require_profile_completed, only: [:create]
before_action :load_repository before_action :load_repository
before_action :check_menu_authorize before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits] before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
before_action :load_pull_request, only: [:files, :commits] before_action :load_pull_request, only: [:files, :commits]
before_action :find_atme_receivers, only: [:create, :update] before_action :find_atme_receivers, only: [:create, :update]
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user)) issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@all_issues = issues.distinct @all_issues = issues.distinct
@filter_issues = @all_issues @filter_issues = @all_issues
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present? @filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN}) @open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED}) @close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED}) @merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})

View File

@ -1,390 +1,390 @@
class RepositoriesController < ApplicationController class RepositoriesController < ApplicationController
include RepositoriesHelper include RepositoriesHelper
include ApplicationHelper include ApplicationHelper
include OperateProjectAbilityAble include OperateProjectAbilityAble
include Repository::LanguagesPercentagable include Repository::LanguagesPercentagable
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror] before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
before_action :require_profile_completed, only: [:create_file] before_action :require_profile_completed, only: [:create_file]
before_action :load_repository before_action :load_repository
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive] before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
before_action :get_ref, only: %i[entries sub_entries top_counts file archive] before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
before_action :get_statistics, only: %i[top_counts] before_action :get_statistics, only: %i[top_counts]
def files def files
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token) result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
render json: result render json: result
end end
# 新版项目详情 # 新版项目详情
def detail def detail
@user = current_user @user = current_user
@result = Repositories::DetailService.call(@owner, @repository, @user) @result = Repositories::DetailService.call(@owner, @repository, @user)
@project_fork_id = @project.try(:forked_from_project_id) @project_fork_id = @project.try(:forked_from_project_id)
if @project_fork_id.present? if @project_fork_id.present?
@fork_project = Project.find_by(id: @project_fork_id) @fork_project = Project.find_by(id: @project_fork_id)
@fork_project_user = @fork_project.owner @fork_project_user = @fork_project.owner
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
end end
def show def show
@user = current_user @user = current_user
@repo = @project.repository @repo = @project.repository
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil @result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
@project_fork_id = @project.try(:forked_from_project_id) @project_fork_id = @project.try(:forked_from_project_id)
if @project_fork_id.present? if @project_fork_id.present?
@fork_project = Project.find_by(id: @project_fork_id) @fork_project = Project.find_by(id: @project_fork_id)
@fork_project_user = @fork_project.owner @fork_project_user = @fork_project.owner
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception(e.message) tip_exception(e.message)
end end
def entries def entries
@project.increment!(:visits) @project.increment!(:visits)
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id) CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
if @project.educoder? if @project.educoder?
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name) @entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
else else
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call @entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : [] @entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
end end
end end
def top_counts def top_counts
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call @result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
end end
def sub_entries def sub_entries
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
if @project.educoder? if @project.educoder?
if params[:type] === 'file' if params[:type] === 'file'
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri) @sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
logger.info "######### sub_entries: #{@sub_entries}" logger.info "######### sub_entries: #{@sub_entries}"
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
tmp_entries = { tmp_entries = {
"content" => @sub_entries['data']['content'], "content" => @sub_entries['data']['content'],
"type" => "blob" "type" => "blob"
} }
@sub_entries = { @sub_entries = {
"trees"=>tmp_entries, "trees"=>tmp_entries,
"commits" => [{}] "commits" => [{}]
} }
else else
begin begin
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri}) @sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
if @sub_entries.blank? || @sub_entries['status'].to_i === -1 if @sub_entries.blank? || @sub_entries['status'].to_i === -1
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri) @sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
tmp_entries = { tmp_entries = {
"content" => @sub_entries['data']['content'], "content" => @sub_entries['data']['content'],
"type" => "blob" "type" => "blob"
} }
@sub_entries = { @sub_entries = {
"trees"=>tmp_entries, "trees"=>tmp_entries,
"commits" => [{}] "commits" => [{}]
} }
end end
rescue rescue
return render_error('该文件暂未开放,敬请期待.') return render_error('该文件暂未开放,敬请期待.')
end end
end end
else else
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref) interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
if interactor.success? if interactor.success?
result = interactor.result result = interactor.result
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result @sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
else else
render_error(interactor.error) render_error(interactor.error)
end end
end end
end end
def commits def commits
if @project.educoder? if @project.educoder?
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name) @commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
else else
if params[:filepath].present? if params[:filepath].present?
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri, @hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
else else
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, @hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
end end
end end
end end
def commits_slice def commits_slice
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier, @hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token) sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
end end
def commit def commit
@sha = params[:sha] @sha = params[:sha]
if @project.educoder? if @project.educoder?
return render_error('暂未开放,敬请期待.') return render_error('暂未开放,敬请期待.')
else else
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token) @commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true}) @commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
end end
end end
def tags def tags
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result @tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
end end
def contributors def contributors
if params[:filepath].present? || @project.educoder? if params[:filepath].present? || @project.educoder?
@contributors = [] @contributors = []
else else
result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result @contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
end end
rescue rescue
@contributors = [] @contributors = []
end end
def edit def edit
return render_forbidden if !@project.manager?(current_user) && !current_user.admin? return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
end end
def create_file def create_file
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
if interactor.success? if interactor.success?
@file = interactor.result @file = interactor.result
# create_new_pr(params) # create_new_pr(params)
#如果是更新流水线文件 #如果是更新流水线文件
if params[:pipeline_id] if params[:pipeline_id]
update_pipeline(params[:pipeline_id]) update_pipeline(params[:pipeline_id])
end end
else else
render_error(interactor.error) render_error(interactor.error)
end end
end end
def update_pipeline(pipeline_id) def update_pipeline(pipeline_id)
pipeline = Ci::Pipeline.find(pipeline_id) pipeline = Ci::Pipeline.find(pipeline_id)
if pipeline if pipeline
pipeline.update!(sync: 1) pipeline.update!(sync: 1)
end end
end end
def update_file def update_file
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
if interactor.success? if interactor.success?
@file = interactor.result @file = interactor.result
# TODO: 是否创建pr # TODO: 是否创建pr
# create_new_pr(params) # create_new_pr(params)
render_result(1, "更新成功") render_result(1, "更新成功")
else else
render_error(interactor.error) render_error(interactor.error)
end end
end end
def delete_file def delete_file
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
if interactor.success? if interactor.success?
@file = interactor.result @file = interactor.result
render_result(1, "文件删除成功") render_result(1, "文件删除成功")
else else
render_error(interactor.error) render_error(interactor.error)
end end
end end
def repo_hook def repo_hook
end end
def sync_mirror def sync_mirror
return render_error("正在镜像中..") if @repository.mirror.waiting? return render_error("正在镜像中..") if @repository.mirror.waiting?
@repository.sync_mirror! @repository.sync_mirror!
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id) SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
render_ok render_ok
end end
def readme def readme
if params[:filepath].present? if params[:filepath].present?
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token) result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
else else
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token) result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
end end
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/" @path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
@readme = result[:status] === :success ? result[:body] : nil @readme = result[:status] === :success ? result[:body] : nil
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path) @readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha") render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
rescue rescue
render json: nil render json: nil
end end
def languages def languages
if @project.educoder? if @project.educoder?
render json: {} render json: {}
else else
render json: languages_precentagable render json: languages_precentagable
end end
end end
def archive def archive
domain = Gitea.gitea_config[:domain] domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url] api_url = Gitea.gitea_config[:base_url]
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{CGI.escape(params[:archive])}" archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
file_path = [domain, api_url, archive_url].join file_path = [domain, api_url, archive_url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden? file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
return render_not_found if !request.format.zip? && !request.format.gzip? return render_not_found if !request.format.zip? && !request.format.gzip?
redirect_to file_path redirect_to file_path
end end
def raw def raw
domain = Gitea.gitea_config[:domain] domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url] api_url = Gitea.gitea_config[:base_url]
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}" url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.escape(params[:ref])}"
file_path = [domain, api_url, url].join file_path = [domain, api_url, url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
redirect_to file_path redirect_to file_path
end end
private private
def find_project def find_project
@project = Project.find params[:id] @project = Project.find params[:id]
render_not_found("未找到相关的仓库") unless @project render_not_found("未找到相关的仓库") unless @project
end end
def find_project_with_includes def find_project_with_includes
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id] @project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
end end
def authorizate! def authorizate!
return if current_user && current_user.admin? return if current_user && current_user.admin?
if @project.repository.hidden? && !@project.member?(current_user) if @project.repository.hidden? && !@project.member?(current_user)
render_forbidden render_forbidden
end end
end end
# TODO 获取最新commit信息 # TODO 获取最新commit信息
def project_commits def project_commits
if params[:filepath].present? if params[:filepath].present?
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri, Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
else else
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier, Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
end end
end end
def get_statistics def get_statistics
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size @branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size @tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
end end
def get_ref def get_ref
@ref = params[:ref] || @project&.default_branch @ref = params[:ref] || @project&.default_branch
end end
def get_latest_commit def get_latest_commit
latest_commit = @project.educoder? ? nil : project_commits latest_commit = @project.educoder? ? nil : project_commits
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil @latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0 @commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
end end
def content_params def content_params
{ {
filepath: params[:filepath], filepath: params[:filepath],
branch: params[:branch], branch: params[:branch],
new_branch: params[:new_branch], new_branch: params[:new_branch],
content: params[:content], content: params[:content],
message: params[:message], message: params[:message],
committer: { committer: {
email: current_user.mail, email: current_user.mail,
name: current_user.login name: current_user.login
}, },
identifier: @project.identifier identifier: @project.identifier
} }
end end
def hook_params(hook_type, params) def hook_params(hook_type, params)
# if hook_type == "push" # if hook_type == "push"
# # TODO hook返回的记录中暂时没有文件代码数量的增减暂时根据 commits数量来计算 # # TODO hook返回的记录中暂时没有文件代码数量的增减暂时根据 commits数量来计算
# uploadPushInfo = { # uploadPushInfo = {
# "sha": params["commits"].present? ? params["commits"].last : "", # "sha": params["commits"].present? ? params["commits"].last : "",
# "branch": params["ref"].to_s.split("/").last, # "branch": params["ref"].to_s.split("/").last,
# "modification_lines": params["commits"].length # "modification_lines": params["commits"].length
# } # }
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作 # elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
# uploadPushInfo = { # uploadPushInfo = {
# "branch": params["base"]["ref"].to_s.split("/").last, # "branch": params["base"]["ref"].to_s.split("/").last,
# "sha": params["pull_request"]["merge_base"], # "sha": params["pull_request"]["merge_base"],
# "modification_lines": 1 #pull_request中没有commits数量 # "modification_lines": 1 #pull_request中没有commits数量
# } # }
# else # else
# uploadPushInfo = {} # uploadPushInfo = {}
# end # end
# uploadPushInfo # uploadPushInfo
end end
def create_new_pr(params) def create_new_pr(params)
if params[:new_branch].present? && params[:new_branch] != params[:branch] if params[:new_branch].present? && params[:new_branch] != params[:branch]
local_params = { local_params = {
title: params[:message], #标题 title: params[:message], #标题
body: params[:content], #内容 body: params[:content], #内容
head: params[:new_branch], #源分支 head: params[:new_branch], #源分支
base: params[:branch], #目标分支 base: params[:branch], #目标分支
milestone: 0 #里程碑,未与本地的里程碑关联 milestone: 0 #里程碑,未与本地的里程碑关联
} }
requests_params = local_params.merge({ requests_params = local_params.merge({
assignee: current_user.try(:login), assignee: current_user.try(:login),
assignees: [], assignees: [],
labels: [], labels: [],
due_date: Time.now due_date: Time.now
}) })
issue_params = { issue_params = {
author_id: current_user.id, author_id: current_user.id,
project_id: @project.id, project_id: @project.id,
subject: params[:message], subject: params[:message],
description: params[:content], description: params[:content],
assigned_to_id: nil, assigned_to_id: nil,
fixed_version_id: nil, fixed_version_id: nil,
issue_tags_value: nil, issue_tags_value: nil,
issue_classify: "pull_request", issue_classify: "pull_request",
issue_type: "1", issue_type: "1",
tracker_id: 2, tracker_id: 2,
status_id: 1, status_id: 1,
priority_id: params[:priority_id] || "2" priority_id: params[:priority_id] || "2"
} }
@pull_issue = Issue.new(issue_params) @pull_issue = Issue.new(issue_params)
if @pull_issue.save! if @pull_issue.save!
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id)) local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
if local_requests.save if local_requests.save
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"]) if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
end end
end end
end end
end end
end end
end end

View File

@ -1,6 +1,7 @@
class SettingsController < ApplicationController class SettingsController < ApplicationController
def show def show
@old_projects_url = nil @old_projects_url = nil
get_navbar
get_add_menu get_add_menu
get_common_menu get_common_menu
get_personal_menu get_personal_menu
@ -9,6 +10,14 @@ class SettingsController < ApplicationController
end end
private private
def get_navbar
@navbar = default_laboratory.navbar
if User.current.logged?
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("link", "/current_user"), "hidden"=>false}
@navbar << pernal_index
end
end
def get_add_menu def get_add_menu
@add = [] @add = []
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site| Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|

View File

@ -12,7 +12,7 @@ class Users::StatisticsController < Users::BaseController
@commit_data = [] @commit_data = []
date_range.each do |date| date_range.each do |date|
@date_data << date.strftime("%Y.%m.%d") @date_data << date.strftime("%Y.%m.%d")
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size @issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size @pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i} date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i) @commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)

View File

@ -49,7 +49,7 @@ class BaseForm
def check_verifi_code(verifi_code, code) def check_verifi_code(verifi_code, code)
code = strip(code) code = strip(code)
# return if code == "123123" # TODO 万能验证码,用于测试 return if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective? raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
end end

View File

@ -1,5 +1,5 @@
class Projects::UpdateForm < BaseForm class Projects::UpdateForm < BaseForm
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier, :project_name
validates :name, presence: true validates :name, presence: true
validates :name, length: { maximum: 50 } validates :name, length: { maximum: 50 }
validates :description, length: { maximum: 200 } validates :description, length: { maximum: 200 }
@ -10,6 +10,7 @@ class Projects::UpdateForm < BaseForm
check_project_language(project_language_id) check_project_language(project_language_id)
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
check_project_name(user_id, name) unless name.blank? || name == project_name
end end
end end

View File

@ -1,148 +1,170 @@
module RepositoriesHelper module RepositoriesHelper
def render_permission(user, project) def render_permission(user, project)
return "Admin" if user&.admin? return "Admin" if user&.admin?
project.get_premission(user) project.get_premission(user)
end end
def render_decode64_content(str) def render_decode64_content(str)
return nil if str.blank? return nil if str.blank?
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace) Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
end end
def download_type(str) def download_type(str)
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv) default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
default_type.include?(str&.downcase) || str.blank? default_type.include?(str&.downcase) || str.blank?
end end
def image_type?(str) def image_type?(str)
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd) default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
default_type.include?(str&.downcase) default_type.include?(str&.downcase)
end end
def is_readme?(type, str) def is_readme?(type, str)
return false if type != 'file' || str.blank? return false if type != 'file' || str.blank?
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"] readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
readme_types.include?(str.to_s.downcase) readme_types.include?(str.to_s.downcase)
end end
def render_commit_author(author_json) def render_commit_author(author_json)
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?) return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
if author_json["id"].present? if author_json["id"].present?
return find_user_by_gitea_uid author_json['id'] return find_user_by_gitea_uid author_json['id']
end end
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?) if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
return find_user_by_login_and_mail(author_json['name'], author_json["email"]) return find_user_by_login_and_mail(author_json['name'], author_json["email"])
end end
end end
def render_cache_commit_author(author_json) def render_cache_commit_author(author_json)
Rails.logger.info author_json['Email'] Rails.logger.info author_json['Email']
if author_json["name"].present? && author_json["email"].present? if author_json["name"].present? && author_json["email"].present?
return find_user_in_redis_cache(author_json['name'], author_json['email']) return find_user_in_redis_cache(author_json['name'], author_json['email'])
end end
if author_json["Name"].present? && author_json["Email"].present? if author_json["Name"].present? && author_json["Email"].present?
return find_user_in_redis_cache(author_json['Name'], author_json['Email']) return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
end end
end end
def readme_render_decode64_content(str, owner, repo, ref) def readme_render_decode64_content(str, owner, repo, ref, path)
return nil if str.blank? return nil if str.blank?
begin begin
content = Base64.decode64(str).force_encoding('UTF-8') content = Base64.decode64(str).force_encoding('UTF-8')
c_regex = /\!\[.*?\]\((.*?)\)/ c_regex = /\!\[.*?\]\((.*?)\)/
src_regex = /src=\"(.*?)\"/ src_regex = /src=\"(.*?)\"/
ss = content.to_s.scan(c_regex) src2_regex = /src='(.*?)'/
ss_src = content.to_s.scan(src_regex) ss = content.to_s.scan(c_regex)
total_images = ss + ss_src ss_src = content.scan(src_regex)
if total_images.length > 0 ss_src2 = content.scan(src2_regex)
total_images.each do |s| total_images = ss + ss_src + ss_src2
image_title = /\"(.*?)\"/ if total_images.length > 0
r_content = s[0] total_images.each do |s|
remove_title = r_content.to_s.scan(image_title) begin
if remove_title.length > 0 image_title = /\"(.*?)\"/
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip r_content = s[0]
end remove_title = r_content.to_s.scan(image_title)
# if r_content.include?("?") # if remove_title.length > 0
# new_r_content = r_content + "&raw=true" # r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
# else # end
# new_r_content = r_content + "?raw=true" path_last = r_content
# end path_current = ""
new_r_content = r_content # 相对路径处理
if r_content.start_with?("../")
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:") relative_path_length = r_content.split("../").size - 1
# new_r_content = "#{path}" + new_r_content path_pre = path.split("/").size - 1 - relative_path_length
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{r_content}&ref=#{ref}"].join path_pre = 0 if path_pre < 0
end path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
content = content.gsub(/#{r_content}/, new_r_content) path_last = r_content.split("../").last
end elsif r_content.start_with?("/") # 根路径处理
end path_last = r_content[1..r_content.size]
else
return content path_current = path
rescue end
return str # if r_content.include?("?")
end # new_r_content = r_content + "&raw=true"
end # else
# new_r_content = r_content + "?raw=true"
# unix_time values for example: 1604382982 # end
def render_format_time_with_unix(unix_time) new_r_content = r_content
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
end unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
# new_r_content = "#{path}" + new_r_content
# date for example: 2020-11-01T19:57:27+08:00 new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
def render_format_time_with_date(date) end
date.to_time.strftime("%Y-%m-%d %H:%M") content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
end rescue
next
def decode64_content(entry, owner, repo, ref, path=nil) end
if is_readme?(entry['type'], entry['name']) end
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] end
readme_render_decode64_content(content, owner, repo, ref)
else return content
file_type = File.extname(entry['name'].to_s)[1..-1] rescue
if image_type?(file_type) return str
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content'] end
end end
if download_type(file_type)
return entry['content'] # unix_time values for example: 1604382982
end def render_format_time_with_unix(unix_time)
render_decode64_content(entry['content']) Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
end end
end
# date for example: 2020-11-01T19:57:27+08:00
def base64_to_image(path, content) def render_format_time_with_date(date)
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png" date.to_time.strftime("%Y-%m-%d %H:%M")
content = Base64.decode64(content) end
File.open(path, 'wb') { |f| f.write(content) }
end def decode64_content(entry, owner, repo, ref, path=nil)
if is_readme?(entry['type'], entry['name'])
def render_download_image_url(dir_path, file_path, content) # content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/") content = entry['content']
file_name = full_path.split("/")[-1] path = URI.escape(entry['path']).to_s.downcase.gsub("/readme.md","")
# 用户名/项目标识/文件路径 readme_render_decode64_content(content, owner, repo, ref, path)
dir_path = generate_dir_path(full_path.split("/"+file_name)[0]) else
file_type = File.extname(entry['name'].to_s)[1..-1]
file_path = [dir_path, file_name].join('/') if image_type?(file_type)
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
puts "##### render_download_image_url file_path: #{file_path}" end
base64_to_image(file_path, content) if download_type(file_type)
file_path = file_path[6..-1] return entry['content']
File.join(base_url, file_path) end
end render_decode64_content(entry['content'])
end
def generate_dir_path(dir_path) end
# tmp_dir_path
# eg: jasder/forgeplus/raw/branch/ref def base64_to_image(path, content)
dir_path = ["public", tmp_dir, dir_path].join('/') # generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
puts "#### dir_path: #{dir_path}" content = Base64.decode64(content)
unless Dir.exists?(dir_path) File.open(path, 'wb') { |f| f.write(content) }
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常 end
end
dir_path def render_download_image_url(dir_path, file_path, content)
end full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
file_name = full_path.split("/")[-1]
def tmp_dir # 用户名/项目标识/文件路径
"repo" dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
end
file_path = [dir_path, file_name].join('/')
end
puts "##### render_download_image_url file_path: #{file_path}"
base64_to_image(file_path, content)
file_path = file_path[6..-1]
File.join(base_url, file_path)
end
def generate_dir_path(dir_path)
# tmp_dir_path
# eg: jasder/forgeplus/raw/branch/ref
dir_path = ["public", tmp_dir, dir_path].join('/')
puts "#### dir_path: #{dir_path}"
unless Dir.exists?(dir_path)
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
end
dir_path
end
def tmp_dir
"repo"
end
end

21
app/libs/trace.rb Normal file
View File

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

View File

@ -29,6 +29,11 @@ class Team < ApplicationRecord
has_many :team_units, dependent: :destroy has_many :team_units, dependent: :destroy
has_many :team_users, dependent: :destroy has_many :team_users, dependent: :destroy
scope :like, lambda { |keywords|
sql = "teams.nickname LIKE :search OR teams.name LIKE :search"
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
}
validates :name, uniqueness: {scope: :organization_id} validates :name, uniqueness: {scope: :organization_id}
enum authorize: {read: 1, write: 2, admin: 3, owner: 4} enum authorize: {read: 1, write: 2, admin: 3, owner: 4}

58
app/models/trace_user.rb Normal file
View File

@ -0,0 +1,58 @@
# == Schema Information
#
# Table name: trace_users
#
# id :integer not null, primary key
# user_id :integer
# username :string(255)
# password :string(255)
# unit :string(255)
# telnumber :string(255)
# email :string(255)
# name :string(255)
# token :text(65535)
# expired_at :datetime
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_trace_users_on_user_id (user_id)
#
# 代码溯源 用户
class TraceUser < ApplicationRecord
belongs_to :user
def build_self_data
return if user.nil?
self.username = user.login
self.password = SecureRandom.hex
self.unit = user.custom_department.blank? ? 'GitLink' : user.custom_department
self.telnumber = user.phone.blank? ? '13800000000' : user.phone
self.email = user.mail
self.name = user.nickname.blank? ? user.login : user.nickname
self
end
def build_token
return if username.blank? || password.blank? || unit.blank? || telnumber.blank? || email.blank? || name.blank?
response = Trace::AddUserService.call(username, password, unit, telnumber, email, name)
self.token = response[1]['token']
self.expired_at = Time.now + 1.hours
end
def refresh_token
return if username.blank? || password.blank? || unit.blank? || telnumber.blank? || email.blank? || name.blank?
response = Trace::LoginService.call(username, password)
self.token = response[1]['token']
self.expired_at = Time.now + 1.hours
end
end

View File

@ -174,6 +174,7 @@ class User < Owner
has_many :system_notification_histories has_many :system_notification_histories
has_many :system_notifications, through: :system_notification_histories has_many :system_notifications, through: :system_notification_histories
has_one :trace_user, dependent: :destroy
# Groups and active users # Groups and active users
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) } scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
@ -789,6 +790,24 @@ class User < Owner
self.nickname.present? && self.mail.present? self.nickname.present? && self.mail.present?
end end
def trace_token
if trace_user.present?
if trace_user.expired_at < Time.now
trace_user.refresh_token
trace_user.save
end
return trace_user.token
else
tu = TraceUser.new
tu.user = self
tu.build_self_data
tu.build_token
tu.save
return tu.token
end
end
protected protected
def validate_password_length def validate_password_length
# 管理员的初始密码是5位 # 管理员的初始密码是5位

View File

@ -27,12 +27,12 @@ class Issues::ListQueryService < ApplicationService
issues = issues.joins(:pull_request).where(pull_requests: {status: 1}) issues = issues.joins(:pull_request).where(pull_requests: {status: 1})
end end
if search_name.present? # if search_name.present?
issues = issues.where("subject LIKE ? OR description LIKE ? ", "%#{search_name}%", "%#{search_name}%") # issues = issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{search_name}%", "%#{search_name}%")
end # end
if start_time&.present? || end_time&.present? if start_time&.present? || end_time&.present?
issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date) issues = issues.where("issues.start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date)
end end
issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all" issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all"

View File

@ -132,8 +132,8 @@ class PullRequests::CreateService < ApplicationService
end end
def merge_original_pull_params def merge_original_pull_params
base_pull_params[:head] = CGI.escape(base_pull_params[:head]) base_pull_params[:head] = Addressable::URI.escape(base_pull_params[:head])
base_pull_params[:base] = CGI.escape(base_pull_params[:base]) base_pull_params[:base] = Addressable::URI.escape(base_pull_params[:base])
if pull_request.is_original && @params[:merge_user_login] if pull_request.is_original && @params[:merge_user_login]
base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{base_pull_params[:head]}") base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{base_pull_params[:head]}")
else else
@ -157,6 +157,7 @@ class PullRequests::CreateService < ApplicationService
raise "head参数不能为空" if @params[:head].blank? raise "head参数不能为空" if @params[:head].blank?
raise "base参数不能为空" if @params[:base].blank? raise "base参数不能为空" if @params[:base].blank?
raise "fork_project_id参数错误" if is_original && !@project.forked_projects.pluck(:id).include?(@params[:fork_project_id].to_i) raise "fork_project_id参数错误" if is_original && !@project.forked_projects.pluck(:id).include?(@params[:fork_project_id].to_i)
raise "merge_user_login参数错误" if is_original && @project.fork_users.joins(:user).where(users: {login: @params[:merge_user_login]}).blank?
raise "分支内容相同,无需创建合并请求" if @params[:head] === @params[:base] && !is_original raise "分支内容相同,无需创建合并请求" if @params[:head] === @params[:base] && !is_original
raise "合并请求已存在" if @project&.pull_requests.where(head: @params[:head], base: @params[:base], status: 0, is_original: is_original, fork_project_id: @params[:fork_project_id]).present? raise "合并请求已存在" if @project&.pull_requests.where(head: @params[:head], base: @params[:base], status: 0, is_original: is_original, fork_project_id: @params[:fork_project_id]).present?
raise @pull_issue.errors.full_messages.join(", ") unless pull_issue.valid? raise @pull_issue.errors.full_messages.join(", ") unless pull_issue.valid?
@ -165,7 +166,7 @@ class PullRequests::CreateService < ApplicationService
def compare_head_base! def compare_head_base!
head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head] head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head]
compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(@params[:base]), CGI.escape(head), @current_user.gitea_token) compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(@params[:base]), Addressable::URI.escape(head), @current_user.gitea_token)
raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank? raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank?
end end

View File

@ -0,0 +1,37 @@
# 代码溯源 添加用户
class Trace::AddUserService < Trace::ClientService
# 用户名 密码 单位 手机号 邮箱 昵称
attr_accessor :username, :password, :unit, :telnumber, :email, :name
def initialize(username, password, unit, telnumber, email, name)
@username = username
@password = password
@unit = unit
@telnumber = telnumber
@email = email
@name = name
end
def call
result = post(url, {data: request_params})
response = render_response(result)
end
private
def request_params
{
username: username,
password: password,
unit: unit,
telnumber: telnumber,
email: email,
name: name
}
end
def url
"/user/addccfuser".freeze
end
end

View File

@ -0,0 +1,33 @@
# 代码溯源 查询检测结果
class Trace::CheckResultService < Trace::ClientService
attr_accessor :token, :project_name, :file_name, :page_num, :page_size
def initialize(token, project_name=nil, file_name=nil, page_num=1, page_size=15)
@token = token
@project_name = project_name
@file_name = file_name
@page_num = page_num
@page_size = page_size
end
def call
result = authed_get(token, url, request_params)
reponse = render_response(result)
end
private
def request_params
{
product_name: project_name,
file_name: file_name,
pageNum: page_num,
pageSize: page_size,
}
end
def url
"/user/checkresult".freeze
end
end

View File

@ -0,0 +1,36 @@
# 代码溯源 开始检测
class Trace::CheckService < Trace::ClientService
attr_accessor :token, :project, :if_branch, :branch_tag
def initialize(token, project, if_branch, branch_tag)
@token = token
@project = project
@if_branch = if_branch
@branch_tag = branch_tag
end
def call
result = authed_post(token, url, {data: request_params})
reponse = render_response(result)
end
private
def request_params
repo = Gitea::Repository::GetService.call(project&.owner&.login, project&.identifier)
{
product_name: project&.name,
product_type: project&.category&.name,
code_type: project&.language&.name,
product_desc: project&.description,
git_url: repo['clone_url'],
if_branch: if_branch,
branch_tag: branch_tag
}
end
def url
"/user/check".freeze
end
end

View File

@ -0,0 +1,143 @@
class Trace::ClientService < ApplicationService
def post(url, params={})
puts "[trace][POST] request params: #{params}"
conn.post do |req|
req.url full_url(url)
req.body = params[:data].to_json
end
end
def authed_post(token, url, params={})
puts "[trace][POST] request params: #{params}"
puts "[trace][POST] request token: #{token}"
conn.post do |req|
req.url full_url(url)
req.body = params[:data].to_json
req.headers['Authorization'] = token
end
end
def get(url, params={})
puts "[trace][GET] request params: #{params}"
conn.get do |req|
req.url full_url(url, 'get')
params.each_pair do |key, value|
req.params["#{key}"] = value
end
end
end
def authed_get(token, url, params={})
puts "[trace][GET] request params: #{params}"
puts "[trace][GET] request token: #{token}"
conn.get do |req|
req.url full_url(url, 'get')
params.each_pair do |key, value|
req.params["#{key}"] = value
end
req.headers['Authorization'] = token
end
end
def delete(url, params={})
puts "[trace][DELETE] request params: #{params}"
conn.delete do |req|
req.url full_url(url)
req.body = params[:data].to_json
end
end
def authed_delete(token, url, params={})
puts "[trace][DELETE] request params: #{params}"
puts "[trace][DELETE] request token: #{token}"
conn.delete do |req|
req.url full_url(url)
req.body = params[:data].to_json
req.headers['Authorization'] = token
end
end
def patch(url, params={})
puts "[trace][PATCH] request params: #{params}"
conn.patch do |req|
req.url full_url(url)
req.body = params[:data].to_json
end
end
def authed_patch(token, url, params={})
puts "[trace][PATCH] request params: #{params}"
puts "[trace][PATCH] request token: #{token}"
conn.patch do |req|
req.url full_url(url)
req.body = params[:data].to_json
req.headers['Authorization'] = token
end
end
def put(url, params={})
puts "[trace][PUT] request params: #{params}"
conn.put do |req|
req.url full_url(url)
req.body = params[:data].to_json
end
end
def authed_put(token, url, params={})
puts "[trace][PUT] request params: #{params}"
puts "[trace][PUT] request token: #{token}"
conn.put do |req|
req.url full_url(url)
req.body = params[:data].to_json
req.headers['Authorization'] = token
end
end
private
def conn
@client ||= begin
Faraday.new(url: domain) do |req|
req.request :url_encoded
req.headers['Content-Type'] = 'application/json'
req.adapter Faraday.default_adapter
end
end
@client
end
def base_url
Trace.trace_config[:base_url]
end
def domain
Trace.trace_config[:domain]
end
def api_url
[domain, base_url].join('')
end
def full_url(api_rest, action='post')
url = [api_url, api_rest].join('').freeze
url = action === 'get' ? url : URI.escape(url)
url = URI.escape(url) unless url.ascii_only?
puts "[trace] request url: #{url}"
return url
end
def log_error(status, body)
puts "[trace] status: #{status}"
puts "[trace] body: #{body}"
end
def render_response(response)
status = response.status
body = JSON.parse(response&.body)
log_error(status, body)
return [body["code"], body["Data"], body["Error"]]
end
end

View File

@ -0,0 +1,29 @@
# 代码溯源 用户登录
class Trace::LoginService < Trace::ClientService
# 用户名 密码
attr_accessor :username, :password
def initialize(username, password)
@username = username
@password = password
end
def call
result = post(url, {data: request_params})
response = render_response(result)
end
private
def request_params
{
username: username,
password: password,
}
end
def url
"/user/login".freeze
end
end

View File

@ -0,0 +1,26 @@
# 代码溯源 导出pdf
class Trace::PdfReportService < Trace::ClientService
attr_accessor :token, :task_id
def initialize(token, task_id)
@token = token
@task_id = task_id
end
def call
result = authed_get(token, url, request_params)
response = render_response(result)
end
private
def request_params
{
task_id: task_id
}
end
def url
"/user/pdfreport".freeze
end
end

View File

@ -0,0 +1,25 @@
# 代码溯源 重新检测
class Trace::ReloadCheckService < Trace::ClientService
attr_accessor :token, :fake_project_id
def initialize(token, fake_project_id)
@token = token
@fake_project_id = fake_project_id
end
def call
result = authed_post(token, url, {data: request_params})
response = render_response(result)
end
private
def request_params
{
project_id: fake_project_id
}
end
def url
'/user/reloadcheck'.freeze
end
end

View File

@ -3,5 +3,5 @@ json.user do
json.partial! "organizations/user_detail", user: org_user.user json.partial! "organizations/user_detail", user: org_user.user
end end
json.team_names org_user.teams.pluck(:name) json.team_names org_user.teams.pluck(:nickname)
json.created_at org_user.created_at.strftime("%Y-%m-%d") json.created_at org_user.created_at.strftime("%Y-%m-%d")

View File

@ -1,4 +1,5 @@
if @project.forge? if @project.forge?
is_dir = @sub_entries.is_a?(Array)
file_name = entry['name'] file_name = entry['name']
file_type = File.extname(file_name.to_s)[1..-1] file_type = File.extname(file_name.to_s)[1..-1]
direct_download = download_type(file_type) direct_download = download_type(file_type)
@ -9,16 +10,16 @@ if @project.forge?
json.type entry['type'] json.type entry['type']
json.size entry['size'] json.size entry['size']
json.content direct_download ? nil : decode64_content(entry, @owner, @repository, @ref, @path) json.content (direct_download || image_type || is_dir) ? nil : decode64_content(entry, @owner, @repository, @ref, @path)
json.target entry['target'] json.target entry['target']
download_url = download_url =
if image_type if image_type
dir_path = [@owner.login, @repository.identifier, "raw/branch", @ref].join('/') dir_path = [@owner.login, @repository.identifier, "raw/branch", @ref].join('/')
render_download_image_url(dir_path, entry['path'], decode64_content(entry, @owner, @repository, @ref)) is_dir ? "" : render_download_image_url(dir_path, entry['path'], decode64_content(entry, @owner, @repository, @ref))
else else
# entry['download_url'] # entry['download_url']
render_download_file_url(@owner, @repository, entry['path'].to_s, @ref) is_dir ? "" : render_download_file_url(@owner, @repository, entry['path'].to_s, @ref)
end end
json.download_url download_url json.download_url download_url

View File

@ -18,7 +18,7 @@ json.setting do
# #
# end # end
nav_bar = default_setting.navbar # nav_bar = default_setting.navbar
# if User.current.logged? # if User.current.logged?
# nav_bar[2]["link"] = "https://forgeplus.trustie.net/users/#{current_user.login}/projects" # nav_bar[2]["link"] = "https://forgeplus.trustie.net/users/#{current_user.login}/projects"
@ -39,7 +39,7 @@ json.setting do
json.moop_cases_banner_url default_setting.moop_cases_banner_url&.[](1..-1) json.moop_cases_banner_url default_setting.moop_cases_banner_url&.[](1..-1)
json.oj_banner_url default_setting.oj_banner_url&.[](1..-1) json.oj_banner_url default_setting.oj_banner_url&.[](1..-1)
json.navbar nav_bar json.navbar @navbar
json.footer default_setting.footer json.footer default_setting.footer

View File

@ -67,6 +67,10 @@ default: &default
write_domain: '' write_domain: ''
read_domain: '' read_domain: ''
base_url: '' base_url: ''
trace:
domain: ''
base_url: ''
forum: forum:
domain: '' domain: ''

View File

@ -692,7 +692,6 @@ Rails.application.routes.draw do
resources :experience_forums resources :experience_forums
resources :pinned_forums resources :pinned_forums
end end
resources :project_statistics, only: [:index] do resources :project_statistics, only: [:index] do
collection do collection do
get :visits_static get :visits_static

View File

@ -0,0 +1,17 @@
class CreateTraceUsers < ActiveRecord::Migration[5.2]
def change
create_table :trace_users do |t|
t.references :user
t.string :username
t.string :password
t.string :unit
t.string :telnumber
t.string :email
t.string :name
t.text :token
t.datetime :expired_at
t.timestamps
end
end
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe TraceUser, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end