forked from Trustie/forgeplus
Merge branch 'standalone_develop' into dev_local_v2
This commit is contained in:
commit
a15f72272d
|
|
@ -134,11 +134,11 @@ $(document).on('turbolinks:load', function() {
|
|||
rules: {
|
||||
"user[password]": {
|
||||
required: false,
|
||||
minlength: 5
|
||||
minlength: 8
|
||||
},
|
||||
"user[password_confirmation]": {
|
||||
required: false,
|
||||
minlength: 5,
|
||||
minlength: 8,
|
||||
equalTo: "#user_password"
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -292,6 +292,7 @@ class AccountsController < ApplicationController
|
|||
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
||||
user.update_column(:last_login_on, Time.now)
|
||||
session[:"#{default_yun_session}"] = user.id
|
||||
UserOnline.login(user.id)
|
||||
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
||||
# 注册完成后有一天的试用申请(先去掉)
|
||||
# UserDayCertification.create(user_id: user.id, status: 1)
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
CommitLog.count
|
||||
end
|
||||
|
||||
@subject_name = ["用户数", "项目数", "组织数", "Issue数", "Issue评论数", "PR数", "Commit数"]
|
||||
@subject_icon = ["fa-user","fa-git", "fa-sitemap", "fa-warning", "fa-comments", "fa-share-alt", "fa-upload"]
|
||||
@subject_data = [@user_count, @project_count, @organization_count, @issue_count, @comment_count, @pr_count, @commit_count]
|
||||
@subject_name = ["用户数", "项目数", "组织数", "Issue数", "Issue评论数", "PR数", "Commit数", "在线用户数"]
|
||||
@subject_icon = ["fa-user","fa-git", "fa-sitemap", "fa-warning", "fa-comments", "fa-share-alt", "fa-upload", "fa-user"]
|
||||
@subject_data = [@user_count, @project_count, @organization_count, @issue_count, @comment_count, @pr_count, @commit_count, UserOnline.count]
|
||||
|
||||
if EduSetting.get("open_baidu_tongji").to_s == "true"
|
||||
tongji_service = Baidu::TongjiService.new
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class Admins::LaboratorySettingsController < Admins::BaseController
|
|||
|
||||
def form_params
|
||||
params.permit(:identifier, :name,
|
||||
:nav_logo, :login_logo, :tab_logo, :oj_banner,
|
||||
:nav_logo, :login_logo, :tab_logo, :pm_logo, :oj_banner,
|
||||
:subject_banner, :course_banner, :competition_banner, :moop_cases_banner,
|
||||
:footer, navbar: %i[name link hidden index])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class Api::Pm::DashboardsController < Api::Pm::BaseController
|
|||
@all_issues = Issue.where(pm_project_id: pm_project_ids, pm_issue_type: pm_issue_types).order(created_on: :desc)
|
||||
@issues = @all_issues.joins(:issue_participants).where(issue_participants: {participant_id: current_user.id, participant_type: 'assigned'})
|
||||
@issues = @issues.where.not(status_id: 5) if params[:category] == "opened"
|
||||
@issues = @issues.where("issues.id > 0")
|
||||
@issues = kaminari_paginate(@issues.distinct.pm_includes)
|
||||
@my_assign_requirements_count = @all_issues.where(pm_issue_type: 1).joins(:issue_participants).where(issue_participants: {participant_id: current_user.id, participant_type: 'assigned'}).size
|
||||
@my_assign_tasks_count = @all_issues.where(pm_issue_type: 2).joins(:issue_participants).where(issue_participants: {participant_id: current_user.id, participant_type: 'assigned'}).size
|
||||
|
|
|
|||
|
|
@ -19,22 +19,23 @@ class Api::Pm::PipelinesController < Api::Pm::BaseController
|
|||
file = file_info.workflow_id
|
||||
project = Project.find_by(gpid: file_info.repo_id)
|
||||
next if project.blank?
|
||||
unless db_files.include?(".gitea/workflows/#{file}")
|
||||
pipeline = Action::Pipeline.find_or_initialize_by(pipeline_name: file.to_s.gsub(".yml", "").gsub(".yaml", ""),
|
||||
file_name: ".gitea/workflows/#{file}",
|
||||
branch: project.default_branch,
|
||||
is_graphic_design: false,
|
||||
disable: false,
|
||||
project_id: project.id)
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, project.identifier, ".gitea/workflows/#{file}", ref: project.default_branch)
|
||||
if interactor.success?
|
||||
pipeline.yaml = decode64_content(interactor.result, @owner, project.repository, project.default_branch, nil)
|
||||
end
|
||||
pipeline.user_id = current_user.id
|
||||
pipeline.save
|
||||
# 导入的流水线统一先禁用
|
||||
$gitea_hat_client.post_repos_actions_disable(project&.owner&.login, project&.identifier, {query: {workflow: file}}) rescue nil
|
||||
end
|
||||
# unless db_files.include?(".gitea/workflows/#{file}")
|
||||
# pipeline = Action::Pipeline.find_or_initialize_by(pipeline_name: file.to_s.gsub(".yml", "").gsub(".yaml", ""),
|
||||
# file_name: ".gitea/workflows/#{file}",
|
||||
# branch: project.default_branch,
|
||||
# disable: false,
|
||||
# project_id: project.id)
|
||||
# interactor = Repositories::EntriesInteractor.call(@owner, project.identifier, ".gitea/workflows/#{file}", ref: project.default_branch)
|
||||
# if interactor.success?
|
||||
# pipeline.yaml = decode64_content(interactor.result, @owner, project.repository, project.default_branch, nil)
|
||||
# file = interactor.result
|
||||
# pipeline.sha = file['content']['sha']
|
||||
# end
|
||||
# pipeline.user_id = current_user.id
|
||||
# pipeline.save
|
||||
# # 导入的流水线统一先禁用
|
||||
# $gitea_hat_client.post_repos_actions_disable(project&.owner&.login, project&.identifier, {query: {workflow: file}}) rescue nil
|
||||
# end
|
||||
last_action_run = action_runs.where(repo_id: project.gpid).where(workflow_id: file).order(updated: :desc).first
|
||||
last_action_run_json = last_action_run.present? ? {
|
||||
id: last_action_run.id,
|
||||
|
|
|
|||
|
|
@ -5,16 +5,18 @@ class Api::Pm::WeeklyIssuesController < Api::Pm::BaseController
|
|||
return render_error('请输入正确的用户ID.') if params[:user_id].blank?
|
||||
@all_issues = Issue.joins(:issue_participants).where(issue_participants: {participant_id: params[:user_id], participant_type: ['assigned']})
|
||||
@all_issues = @all_issues.where(enterprise_identifier: @enterprise_identifier, pm_issue_type: [1,2,3])
|
||||
@this_week_all_issues = @all_issues.where("due_date >= ? and start_date <= ?", Date.today.beginning_of_week.to_s, Date.today.end_of_week.to_s).distinct
|
||||
@this_week_all_issues = @this_week_all_issues.order('created_on desc')
|
||||
@next_week_all_issues = @all_issues.where("due_date >= ? and start_date <=?", (Date.today.beginning_of_week+1.week).to_s, (Date.today.end_of_week+1.week).to_s).distinct
|
||||
@next_week_all_issues = @next_week_all_issues.order('created_on desc')
|
||||
@weekly_begin_date = params[:weekly_begin_date].to_time || Date.today.beginning_of_week rescue Date.today.beginning_of_week
|
||||
@weekly_end_date = params[:weekly_end_date].to_time || Date.today.end_of_week rescue Date.today.end_of_week
|
||||
@this_week_all_issues = @all_issues.where("due_date >= ? and start_date <= ?", @weekly_begin_date.to_s, @weekly_end_date.to_s).distinct
|
||||
@this_week_all_issues = @this_week_all_issues.order('created_on desc').pm_includes
|
||||
@next_week_all_issues = @all_issues.where("due_date >= ? and start_date <=?", (@weekly_begin_date+1.week).to_s, (@weekly_end_date+1.week).to_s).distinct
|
||||
@next_week_all_issues = @next_week_all_issues.order('created_on desc').pm_includes
|
||||
@this_week_requirement_issues = @this_week_all_issues.where(pm_issue_type: 1)
|
||||
@this_week_task_issues = @this_week_all_issues.where(pm_issue_type: 2)
|
||||
@this_week_bug_issues = @this_week_all_issues.where(pm_issue_type: 3)
|
||||
@close_requirement_issues = @this_week_requirement_issues.where(status_id: [3,5])
|
||||
@close_task_issues = @this_week_task_issues.where(status_id: [3,5])
|
||||
@close_bug_issues = @this_week_bug_issues.where(status_id: [3,5])
|
||||
@close_requirement_issues = @this_week_requirement_issues.where(status_id: [3,5]).pm_includes
|
||||
@close_task_issues = @this_week_task_issues.where(status_id: [3,5]).pm_includes
|
||||
@close_bug_issues = @this_week_bug_issues.where(status_id: [3,5]).pm_includes
|
||||
this_week_page = params[:this_week_page] || 1
|
||||
this_week_limit = params[:this_week_limit] || 15
|
||||
@this_week_all_issues = @this_week_all_issues.page(this_week_page).per(this_week_limit)
|
||||
|
|
@ -27,7 +29,9 @@ class Api::Pm::WeeklyIssuesController < Api::Pm::BaseController
|
|||
@enterprise_identifier = params[:enterprise_identifier] || ''
|
||||
@all_issues = Issue.where(enterprise_identifier: @enterprise_identifier, pm_issue_type: [1,2,3])
|
||||
@all_issues = @all_issues.where(pm_project_id: params[:pm_project_ids].split(",")) if params[:pm_project_ids].present?
|
||||
@this_week_all_issues = @all_issues.where("due_date >= ? and start_date <= ?", Date.today.beginning_of_week.to_s, Date.today.end_of_week.to_s)
|
||||
@weekly_begin_date = params[:weekly_begin_date] || Date.today.beginning_of_week.to_s
|
||||
@weekly_end_date = params[:weekly_end_date] || Date.today.end_of_week.to_s
|
||||
@this_week_all_issues = @all_issues.where("due_date >= ? and start_date <= ?", @weekly_begin_date, @weekly_end_date)
|
||||
@this_week_all_issues_group_count = @this_week_all_issues.group(:pm_project_id).count
|
||||
data = {}
|
||||
@this_week_all_issues_group_count.keys.each do |pm_project_id|
|
||||
|
|
@ -69,7 +73,7 @@ class Api::Pm::WeeklyIssuesController < Api::Pm::BaseController
|
|||
@all_issues = @all_issues.where(pm_project_id: params[:pm_project_ids].split(",")) if params[:pm_project_ids].present?
|
||||
@all_issues = @all_issues.where(pm_issue_type: params[:pm_issue_type].to_i) if params[:pm_issue_type].present?
|
||||
@this_week_all_issues = @all_issues.where("due_date >= ? and start_date <= ?", @weekly_begin_date, @weekly_end_date)
|
||||
@this_week_all_issues = @this_week_all_issues.order('created_on desc')
|
||||
@this_week_all_issues = @this_week_all_issues.order('created_on desc').pm_includes
|
||||
@this_week_all_issues = kaminari_paginate(@this_week_all_issues)
|
||||
end
|
||||
def personal_issues
|
||||
|
|
@ -86,9 +90,9 @@ class Api::Pm::WeeklyIssuesController < Api::Pm::BaseController
|
|||
end
|
||||
@all_issues = @all_issues.where(enterprise_identifier: @enterprise_identifier, pm_issue_type: [1,2,3])
|
||||
@this_week_all_issues = @all_issues.where("due_date >= ? and start_date <= ?", @weekly_begin_date, @weekly_end_date).distinct
|
||||
@this_week_all_issues = @this_week_all_issues.order('created_on desc')
|
||||
@this_week_all_issues = @this_week_all_issues.order('created_on desc').pm_includes
|
||||
@next_week_all_issues = @all_issues.where("due_date >= ? and start_date <=?", (@weekly_begin_date.to_date+1.week).to_s, (@weekly_end_date.to_date+1.week).to_s).distinct
|
||||
@next_week_all_issues = @next_week_all_issues.order('created_on desc')
|
||||
@next_week_all_issues = @next_week_all_issues.order('created_on desc').pm_includes
|
||||
this_week_page = params[:this_week_page] || 1
|
||||
this_week_limit = params[:this_week_limit] || 15
|
||||
@this_week_all_issues = @this_week_all_issues.page(this_week_page).per(this_week_limit)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ class Api::V1::BaseController < ApplicationController
|
|||
params.fetch(:page, 1)
|
||||
end
|
||||
|
||||
def load_organization
|
||||
@organization = Organization.find_by(login: params[:owner]) || Organization.find_by(id: params[:owner])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
end
|
||||
|
||||
# 具有对仓库的管理权限
|
||||
def require_manager_above
|
||||
@project = load_project
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
class Api::V1::Organizations::ProjectsController < Api::V1::BaseController
|
||||
before_action :load_organization
|
||||
|
||||
def index
|
||||
public_projects_sql = @organization.projects.where(is_public: true).to_sql
|
||||
private_projects_sql = @organization.projects
|
||||
.where(is_public: false)
|
||||
.joins(team_projects: {team: :team_users})
|
||||
.where(team_users: {user_id: current_user.id}).to_sql
|
||||
@projects = Project.from("( #{ public_projects_sql} UNION #{ private_projects_sql } ) AS projects")
|
||||
# 表情处理
|
||||
keywords = params[:search].to_s.each_char.select { |c| c.bytes.first < 240 }.join('')
|
||||
@projects = @projects.where(is_public: params[:is_public]) if params[:is_public].present?
|
||||
@projects = @projects.where(id: params[:pm_project_repository_ids].split(',')) if params[:pm_project_repository_ids].present?
|
||||
@projects = @projects.where.not(id: params[:exclude_ids].to_s.split(",")) if params[:exclude_ids].present?
|
||||
@projects = @projects.where(project_type: ['mirror', 'common']).where("gpid is not null") if params[:actived].present?
|
||||
@projects = @projects.ransack(name_or_identifier_cont: keywords).result if params[:search].present?
|
||||
@projects = @projects.includes(:owner).order("projects.#{sort} #{sort_direction}")
|
||||
@projects = kaminari_paginate(@projects)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_organization
|
||||
@organization = Organization.find_by(login: params[:owner]) || Organization.find_by(id: params[:owner])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
end
|
||||
|
||||
def org_limited_condition
|
||||
@organization.organization_extension.limited? && !current_user.logged?
|
||||
end
|
||||
|
||||
def org_privacy_condition
|
||||
return false if current_user.admin?
|
||||
@organization.organization_extension.privacy? && @organization.organization_users.where(user_id: current_user.id).blank?
|
||||
end
|
||||
|
||||
def sort
|
||||
Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'updated_on'
|
||||
end
|
||||
|
||||
def sort_direction
|
||||
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
class Api::V1::Organizations::SyncRepositoriesController < Api::V1::BaseController
|
||||
before_action :load_organization, only: [:create]
|
||||
|
||||
def create
|
||||
return render_error("请输入正确的外部组织login") unless params[:external_login].present?
|
||||
# 拉取外部组织仓库列表
|
||||
url = URI("https://api.github.com/orgs/#{params[:external_login]}/repos?page=#{params[:page]}&per_page=#{params[:limit]}")
|
||||
https = Net::HTTP.new(url.host, url.port)
|
||||
https.use_ssl = true
|
||||
request = Net::HTTP::Get.new(url)
|
||||
request["Authorization"] = "Bearer #{params[:external_token]}"
|
||||
response = https.request(request)
|
||||
if response.code == "200"
|
||||
repos = JSON.parse(response.body)
|
||||
repos.each do |repo|
|
||||
# 检查是否已经存在该仓库
|
||||
@project = @organization.projects.find_by(identifier: repo["name"])
|
||||
if @project.present?
|
||||
if @project.repository.mirror.failed?
|
||||
@project.destroy!
|
||||
mirror_params = {name: repo["name"], user_id: @organization.id, description: repo["description"], repository_name: repo["name"], auth_token: params[:external_token], clone_addr: repo["clone_url"]}
|
||||
@project = ::Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
@project.update_column(:created_on, repo['created_at'].to_time)
|
||||
@project.update_column(:updated_on, repo['updated_at'].to_time)
|
||||
next
|
||||
else
|
||||
mirror_params = {name: repo["name"], user_id: @organization.id, description: repo["description"], repository_name: repo["name"], auth_token: params[:external_token], clone_addr: repo["clone_url"]}
|
||||
@project = ::Projects::MigrateService.call(current_user, mirror_params)
|
||||
@project.update_column(:created_on, repo['created_at'].to_time)
|
||||
@project.update_column(:updated_on, repo['updated_at'].to_time)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def sync_repository_params
|
||||
params.permit(:external_token)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -58,4 +58,15 @@ class Api::V1::Projects::Actions::RunsController < Api::V1::Projects::Actions::B
|
|||
redirect_to file_path
|
||||
end
|
||||
|
||||
def cancel
|
||||
return render_error("请输入正确的流水线记录ID!") if params[:run_id].blank?
|
||||
http = Gitea::Api::Hat::Http.new($gitea_hat_client.config)
|
||||
gitea_result = http.post("/repos/#{@project&.owner&.login}/#{@project&.identifier}/actions/runs/#{params[:run_id]}/cancel") rescue nil
|
||||
if gitea_result
|
||||
render_ok
|
||||
else
|
||||
render_error("停止流水线任务失败")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
||||
include RepositoriesHelper
|
||||
include Api::ActionValidatorHelper
|
||||
before_action :require_operate_above, except: [:upload_results, :run_results]
|
||||
|
||||
def index
|
||||
|
|
@ -10,22 +11,22 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
|||
db_files = pipelines.pluck(:file_name)
|
||||
@run_result = []
|
||||
@files.map { |i| i['name'] }.each do |file|
|
||||
unless db_files.include?(".gitea/workflows/#{file}")
|
||||
pipeline = Action::Pipeline.find_or_initialize_by(pipeline_name: file.to_s.gsub(".yml", "").gsub(".yaml", ""),
|
||||
file_name: ".gitea/workflows/#{file}",
|
||||
branch: @project.default_branch,
|
||||
is_graphic_design: false,
|
||||
disable: false,
|
||||
project_id: @project.id)
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, ".gitea/workflows/#{file}", ref: @project.default_branch)
|
||||
if interactor.success?
|
||||
pipeline.yaml = decode64_content(interactor.result, @owner, @project.repository, @project.default_branch, nil)
|
||||
end
|
||||
pipeline.user_id = current_user.id
|
||||
pipeline.save
|
||||
# 导入的流水线统一先禁用
|
||||
$gitea_hat_client.post_repos_actions_disable(@project&.owner&.login, @project&.identifier, {query: {workflow: file}}) rescue nil
|
||||
end
|
||||
# unless db_files.include?(".gitea/workflows/#{file}")
|
||||
# pipeline = Action::Pipeline.find_or_initialize_by(pipeline_name: file.to_s.gsub(".yml", "").gsub(".yaml", ""),
|
||||
# file_name: ".gitea/workflows/#{file}",
|
||||
# branch: @project.default_branch,
|
||||
# is_graphic_design: false,
|
||||
# disable: false,
|
||||
# project_id: @project.id)
|
||||
# interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, ".gitea/workflows/#{file}", ref: @project.default_branch)
|
||||
# if interactor.success?
|
||||
# pipeline.yaml = decode64_content(interactor.result, @owner, @project.repository, @project.default_branch, nil)
|
||||
# end
|
||||
# pipeline.user_id = current_user.id
|
||||
# pipeline.save
|
||||
# # 导入的流水线统一先禁用
|
||||
# $gitea_hat_client.post_repos_actions_disable(@project&.owner&.login, @project&.identifier, {query: {workflow: file}}) rescue nil
|
||||
# end
|
||||
last_action_run = @action_runs.where(workflow_id: file).order(updated: :desc).first
|
||||
last_action_run_json = last_action_run.present? ? {
|
||||
id: last_action_run.id,
|
||||
|
|
@ -79,12 +80,20 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
|||
tip_exception("已经存在#{params[:pipeline_name]}流水线!") if has_pipeline.present?
|
||||
if @pipeline.yaml.present?
|
||||
sha = get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
|
||||
if sha.present?
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params("update", params[:pipeline_name]).merge(sha: sha, from_path: "#{@pipeline.pipeline_name}"))
|
||||
new_file_sha = get_pipeline_file_sha(".gitea/workflows/#{params[:pipeline_name]}.yml", @pipeline.branch)
|
||||
# 重命名的新文件存在时,直接修改新文件new_file_sha, 同时删除老文件
|
||||
if sha.present? && new_file_sha.present?
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params("update", params[:pipeline_name]).merge(sha: new_file_sha, from_path: ".gitea/workflows/#{params[:pipeline_name]}.yml"))
|
||||
tip_exception(interactor.error) unless interactor.success?
|
||||
del_interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, del_content_params(sha).merge(identifier: @project.identifier))
|
||||
tip_exception(del_interactor.error) unless del_interactor.success?
|
||||
elsif sha.present? && new_file_sha.blank?
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params("update", params[:pipeline_name]).merge(sha: sha, from_path: ".gitea/workflows/#{@pipeline.pipeline_name}.yml"))
|
||||
tip_exception(interactor.error) unless interactor.success?
|
||||
end
|
||||
end
|
||||
end
|
||||
@pipeline.user_id = current_user.id
|
||||
@pipeline.pipeline_name = params[:pipeline_name]
|
||||
@pipeline.file_name = ".gitea/workflows/#{@pipeline.pipeline_name}.yml"
|
||||
@pipeline.branch = params[:branch] || @project.default_branch
|
||||
|
|
@ -101,6 +110,10 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
|||
@pipeline.pipeline_name = params[:pipeline_name] if params[:pipeline_name].present?
|
||||
pipeline_yaml = params[:pipeline_yaml].present? ? params[:pipeline_yaml] : build_pipeline_yaml_new(@pipeline.pipeline_name, params[:pipeline_json])
|
||||
tip_exception("流水线yaml内空不能为空") if pipeline_yaml.blank?
|
||||
result = validate_string(pipeline_yaml)
|
||||
unless result[:valid]
|
||||
tip_exception(result[:errors].join(","))
|
||||
end
|
||||
@pipeline.yaml = pipeline_yaml
|
||||
#Rails.logger.info "pipeline_yaml base64=========================#{Base64.encode64(@pipeline.yaml).gsub(/\n/, '')}"
|
||||
sha = get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
|
||||
|
|
@ -108,7 +121,9 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
|
|||
interactor = sha.present? ? Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, content_params("update").merge(sha: sha)) : Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params("create"))
|
||||
tip_exception(interactor.error) unless interactor.success?
|
||||
file = interactor.result
|
||||
@pipeline.user_id = current_user.id if @pipeline.user_id.blank?
|
||||
@pipeline.pipeline_type = @pipeline.json.present? ? 2 : 1
|
||||
@pipeline.sha = sha.present? ? sha : file['content']['sha']
|
||||
@pipeline.save
|
||||
render_ok({ pipeline_yaml: pipeline_yaml, pipeline_name: @pipeline.pipeline_name, file_name: @pipeline.file_name, sha: sha.present? ? sha : file['content']['sha'] })
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,13 +6,32 @@ class Api::V1::Projects::Pulls::PullsController < Api::V1::BaseController
|
|||
@pulls = kaminari_paginate(@pulls)
|
||||
end
|
||||
|
||||
before_action :load_pull_request, only: [:show, :files]
|
||||
before_action :load_pull_request, only: [:show, :reopen, :files]
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::Pulls::GetService.call(@project, @pull_request, current_user&.gitea_token)
|
||||
@last_review = @pull_request.reviews.order(created_at: :desc).take
|
||||
end
|
||||
|
||||
def reopen
|
||||
can_merge = @project&.pull_requests.where(head: @pull_request.head, base: @pull_request.base, status: 0, is_original: @pull_request.is_original, fork_project_id: @pull_request.fork_project_id)
|
||||
if can_merge.present?
|
||||
render json: {
|
||||
status: -1,
|
||||
redirect_url:"/#{@project.owner.login}/#{@project.identifier}/pulls/#{can_merge.first.gitea_number}",
|
||||
message: "在这些分支之间的合并请求已存在",
|
||||
}
|
||||
else
|
||||
@result_object = Api::V1::Projects::Pulls::ReopenService.call(@project, @pull_request, current_user)
|
||||
if @result_object
|
||||
ProjectActions::PullRequestEvent.build(@project, current_user, @pull_request, "reopened")
|
||||
render_ok
|
||||
else
|
||||
render_error("合并请求重新打开失败!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def files
|
||||
if params[:filepath].present?
|
||||
@result_object = $gitea_hat_client.get_repos_pulls_files_by_owner_repo_index_filepath(@project&.owner.login, @project&.identifier, @pull_request.gitea_number, CGI.escape(params[:filepath]), {query: {token: current_user&.gitea_token}})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
class Api::V1::UserTokensController < Api::V1::BaseController
|
||||
include AesCryptHelper
|
||||
before_action :require_login
|
||||
|
||||
def show
|
||||
password = decrypt(params[:password]) rescue params[:password].to_s
|
||||
tip_exception("密码不正确") unless current_user.check_password?(password)
|
||||
render_ok({access_token: current_user.gitea_token})
|
||||
end
|
||||
end
|
||||
|
|
@ -4,7 +4,7 @@ class Api::V1::Users::FeedbacksController < Api::V1::BaseController
|
|||
before_action :check_auth_for_observe_user
|
||||
|
||||
def create
|
||||
@result = Api::V1::Users::Feedbacks::CreateService.call(@observe_user, feedback_params)
|
||||
@result = Api::V1::Users::Feedbacks::CreateService.call(@observe_user, feedback_params, request.remote_ip)
|
||||
return render_error("反馈意见创建失败.") if @result.nil?
|
||||
return render_ok
|
||||
end
|
||||
|
|
|
|||
|
|
@ -326,24 +326,14 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
end
|
||||
elsif params[:access_token].present?
|
||||
user = User.find_by(gitea_token: params[:access_token])
|
||||
tip_exception(401, "无效token") if user.blank?
|
||||
User.current = user
|
||||
else
|
||||
User.current = find_current_user
|
||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
||||
|
||||
# # 开放课程通过链接访问的用户
|
||||
# if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
|
||||
# content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
|
||||
#
|
||||
# if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
|
||||
# user = open_class_user
|
||||
# if user
|
||||
# start_user_session(user)
|
||||
# set_autologin_cookie(user)
|
||||
# end
|
||||
# User.current = user
|
||||
# end
|
||||
# end
|
||||
|
||||
if !User.current.logged? && Rails.env.development?
|
||||
user = User.find 1
|
||||
User.current = user
|
||||
|
|
@ -366,6 +356,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
end
|
||||
UserOnline.login(User.current.id)
|
||||
# User.current = User.find 81403
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class AttachmentsController < ApplicationController
|
|||
Rails.logger.info("request.host===#{request.host},request.referer===#{request.referer}")
|
||||
tip_exception(403, "你没有权限访问") if request.host.present? && !request.referer.to_s.include?(request.host.to_s.gsub("www.",""))
|
||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
tip_exception('不可访问') if params[:download_url].to_s.include?("chinese_dictionary.txt")
|
||||
url = base_url.starts_with?("https:") ? params[:download_url].to_s.gsub("http:", "https:") : params[:download_url].to_s
|
||||
md5_file = Digest::MD5.hexdigest(params[:download_url])
|
||||
FileUtils.mkdir_p("#{Rails.root}#{EduSetting.get("attachment_folder")}gitea/") unless Dir.exists?("#{Rails.root}#{EduSetting.get("attachment_folder")}gitea/")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
require 'yaml'
|
||||
require 'json'
|
||||
|
||||
module Api::ActionValidatorHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def validate_string(yaml_string)
|
||||
begin
|
||||
yaml_content = YAML.safe_load(yaml_string)
|
||||
validate_content(yaml_content)
|
||||
rescue Psych::SyntaxError => e
|
||||
{ valid: false, errors: ["YAML语法错误: #{e.message}"] }
|
||||
rescue => e
|
||||
{ valid: false, errors: ["数据读取错误: #{e.message}"] }
|
||||
end
|
||||
end
|
||||
|
||||
def validate_content(data)
|
||||
errors = []
|
||||
warnings = []
|
||||
|
||||
# 基本结构验证
|
||||
errors.concat(validate_basic_structure(data))
|
||||
|
||||
# 触发器验证
|
||||
# errors.concat(validate_trigger(data))
|
||||
|
||||
# 任务验证
|
||||
errors.concat(validate_job(data))
|
||||
|
||||
# 步骤验证
|
||||
if data['jobs']
|
||||
data['jobs'].each do |job_name, job_config|
|
||||
errors.concat(validate_job_steps(job_name, job_config))
|
||||
end
|
||||
end
|
||||
|
||||
{
|
||||
valid: errors.empty?,
|
||||
errors: errors,
|
||||
warnings: warnings,
|
||||
job_count: data['jobs']&.size || 0
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_basic_structure(data)
|
||||
errors = []
|
||||
|
||||
unless data.is_a?(Hash)
|
||||
errors << "Action文件必须是YAML对象"
|
||||
return errors
|
||||
end
|
||||
|
||||
unless data.key?('name')
|
||||
errors << "缺少必需字段: name"
|
||||
end
|
||||
|
||||
unless data.key?(true)
|
||||
errors << "缺少触发器配置: on"
|
||||
end
|
||||
|
||||
unless data.key?('jobs')
|
||||
errors << "缺少任务配置: jobs"
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_trigger(data)
|
||||
errors = []
|
||||
|
||||
if data[true]
|
||||
if data[true]['push']
|
||||
unless data[true]['push'].key?('branches')
|
||||
errors << "push触发器缺少branches配置"
|
||||
end
|
||||
|
||||
unless data[true]['push'].key?('paths-ignore')
|
||||
errors << "push触发器缺少paths-ignore配置"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_job(data)
|
||||
errors = []
|
||||
|
||||
if data['jobs']
|
||||
jobs = data['jobs']
|
||||
|
||||
unless jobs.is_a?(Hash)
|
||||
errors << "jobs字段必须是对象"
|
||||
return errors
|
||||
end
|
||||
|
||||
jobs.each do |job_name, job_config|
|
||||
unless job_config.is_a?(Hash)
|
||||
errors << "任务 #{job_name} 配置必须是对象"
|
||||
next
|
||||
end
|
||||
|
||||
# unless job_config.key?('name')
|
||||
# errors << "任务 #{job_name} 缺少name字段"
|
||||
# end
|
||||
|
||||
unless job_config.key?('runs-on')
|
||||
errors << "任务 #{job_name} 缺少runs-on字段"
|
||||
end
|
||||
|
||||
unless job_config.key?('steps')
|
||||
errors << "任务 #{job_name} 缺少steps字段"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_job_steps(job_name, job_config)
|
||||
errors = []
|
||||
steps = job_config['steps'] || []
|
||||
|
||||
unless steps.is_a?(Array)
|
||||
errors << "任务 #{job_name} 的steps必须是数组"
|
||||
return errors
|
||||
end
|
||||
# 验证每个步骤的详细配置
|
||||
steps.each_with_index do |step, index|
|
||||
errors.concat(validate_step(job_name, step, index))
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
|
||||
def validate_step(job_name, step, index)
|
||||
errors = []
|
||||
|
||||
unless step.is_a?(Hash)
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 必须是对象"
|
||||
return errors
|
||||
end
|
||||
|
||||
# unless step.key?('name')
|
||||
# errors << "任务 #{job_name} 步骤 #{index + 1} 缺少name字段"
|
||||
# end
|
||||
|
||||
# 验证uses或run字段
|
||||
has_uses = step.key?('uses')
|
||||
has_run = step.key?('run')
|
||||
|
||||
unless has_uses || has_run
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 必须包含uses或run字段"
|
||||
end
|
||||
|
||||
if has_uses && has_run
|
||||
errors << "任务 #{job_name} 步骤 #{index + 1} 不能同时包含uses和run字段"
|
||||
end
|
||||
|
||||
errors
|
||||
end
|
||||
end
|
||||
|
|
@ -63,6 +63,7 @@ module LoginHelper
|
|||
|
||||
user.delete_autologin_token(autologin)
|
||||
user.delete_session_token(session[:tk])
|
||||
UserOnline.logout(User.current.id)
|
||||
self.logged_user = nil
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class JournalsController < ApplicationController
|
|||
AtmeService.call(current_user, @atme_receivers, journal) if @atme_receivers.size > 0
|
||||
TouchWebhookJob.set(wait: 5.seconds).perform_later('PullRequestComment', @issue&.id, current_user.id, journal.id, 'created', {})
|
||||
# @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal")
|
||||
|
||||
ProjectActions::PullRequestReviewCommentEvent.build(@issue.project, current_user, @issue.pull_request, journal) if @issue.issue_classify == "pull_request"
|
||||
# author: zxh
|
||||
# 调用上链API
|
||||
push_activity_2_blockchain("issue_comment_create", journal) if Site.has_blockchain? && @project.use_blockchain
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class MainController < ApplicationController
|
|||
skip_before_action :setup_laboratory
|
||||
|
||||
def first_stamp
|
||||
render :json => { status: 0, message: Time.now.to_i }
|
||||
render :json => { status: 0, message: Time.now.to_i, online: UserOnline.count }
|
||||
end
|
||||
|
||||
def test_404
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class OwnersController < ApplicationController
|
|||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @owner.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 == @owner.login) ? projects : projects.visible
|
||||
@user_projects_count = user_projects.size
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class PullRequestsController < ApplicationController
|
|||
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||
AtmeService.call(current_user, @atme_receivers, @pull_request) if @atme_receivers.size > 0
|
||||
|
||||
ProjectActions::PullRequestEvent.build(@project, current_user, @pull_request, "opened")
|
||||
# author: zxh
|
||||
# 调用上链API
|
||||
push_activity_2_blockchain("pull_request_create", @pull_request) if Site.has_blockchain? && @project.use_blockchain
|
||||
|
|
@ -177,6 +177,7 @@ class PullRequestsController < ApplicationController
|
|||
# 合并请求下issue处理为关闭
|
||||
@issue&.update_attributes!({status_id:5})
|
||||
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||
ProjectActions::PullRequestEvent.build(@project, current_user, @pull_request, "closed")
|
||||
normal_status(1, "已拒绝")
|
||||
else
|
||||
normal_status(-1, '合并失败')
|
||||
|
|
@ -247,6 +248,7 @@ class PullRequestsController < ApplicationController
|
|||
|
||||
# 合并请求下issue处理为关闭
|
||||
@issue&.update_attributes!({status_id:5})
|
||||
ProjectActions::PullRequestEvent.build(@project, current_user, @pull_request, "closed")
|
||||
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||
normal_status(1, "合并成功")
|
||||
else
|
||||
|
|
@ -324,7 +326,7 @@ class PullRequestsController < ApplicationController
|
|||
# milestone: 0, #里程碑,未与本地的里程碑关联
|
||||
}
|
||||
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||
@requests_params = @local_params.merge({assignees: [assignee_login.to_s].reject!(&:empty?)})
|
||||
@requests_params = @local_params.merge({assignees: [assignee_login.to_s].reject{|item|item.empty?}})
|
||||
@issue_params = {
|
||||
author_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
|
||||
tip_exception('不可访问') if params[:filepath].to_s.include?("chinese_dictionary.txt")
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
|
|
@ -307,6 +307,7 @@ class RepositoriesController < ApplicationController
|
|||
def raw
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
tip_exception('不可访问') if params[:filepath].to_s.include?("chinese_dictionary.txt")
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
|
||||
file_path = [domain, api_url, url].join
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class Users::OrganizationsController < Users::BaseController
|
|||
@organizations = observed_user.organizations.with_visibility("common")
|
||||
end
|
||||
|
||||
@organizations = @organizations.ransack(login_cont: params[:search]).result if params[:search].present?
|
||||
@organizations = @organizations.ransack(login_or_nickname_cont: params[:search]).result if params[:search].present?
|
||||
|
||||
@home_top_ids = @organizations.joins(:home_top_settings).where(home_top_settings: {user_id: observed_user.id}).order("home_top_settings.created_at asc").pluck(:id)
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class UsersController < ApplicationController
|
|||
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
|
||||
@user_projects_count = user_projects.size
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class VersionReleasesController < ApplicationController
|
|||
if params[:attachment_ids].present?
|
||||
create_attachments(params[:attachment_ids], version_release)
|
||||
end
|
||||
ProjectActions::ReleaseEvent.build(@project, current_user, version_release)
|
||||
normal_status(0, "发布成功")
|
||||
else
|
||||
normal_status(-1, "发布失败")
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ class WatchersController < ApplicationController
|
|||
def follow
|
||||
begin
|
||||
return normal_status(2, "你已关注了") if current_user.watched?(@target)
|
||||
if @target.is_a?(Project)
|
||||
ProjectActions::StarEvent.build(@target, current_user)
|
||||
end
|
||||
current_user.watch!(@target)
|
||||
render_ok({watchers_count: @target.watchers_count, watched: true})
|
||||
rescue Exception => e
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def render_zip_url(owner, repository, archive)
|
||||
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.zip")].join
|
||||
[base_url, archive_repositories_path(owner&.login, repository.identifier, "#{archive}.zip")].join
|
||||
end
|
||||
|
||||
def render_tar_url(owner, repository, archive)
|
||||
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.tar.gz")].join
|
||||
[base_url, archive_repositories_path(owner&.login, repository.identifier, "#{archive}.tar.gz")].join
|
||||
end
|
||||
|
||||
def render_download_file_url(owner, repository, filepath, ref)
|
||||
|
|
|
|||
|
|
@ -157,10 +157,12 @@ module RepositoriesHelper
|
|||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
ext = ext.split("?")[0] if ext.include?("?")
|
||||
ext = ext.gsub(/ \".*\"/, "") if ext.include?(" ")
|
||||
if (image_type?(ext) || download_type(ext)) && !ext.blank?
|
||||
s_content = s_content.starts_with?("/") ? s_content[1..-1] : s_content[0..-1]
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
s_content = s_content.gsub(/ \".*\"/, "") if s_content.include?(" ")
|
||||
next if s_content.blank?
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
join_xxx = s_content.include?("?") ? "&" : "?"
|
||||
|
|
@ -184,8 +186,16 @@ module RepositoriesHelper
|
|||
content = content.gsub("href=\"#{s[0]}\"", "href=\"#{s_content}\"")
|
||||
when 'ss_href_1'
|
||||
content = content.gsub("href=\'#{s[0]}\'", "href=\'#{s_content}\'")
|
||||
else
|
||||
content = content.gsub("(#{s[0]})", "(#{s_content})")
|
||||
else
|
||||
## md中图片处理包含中文名称,tip
|
||||
if s[0].to_s.include?(" ")
|
||||
s1 = s[0].to_s.split(" ")
|
||||
str1 = s1[0]
|
||||
str2 = s1[1] if s1.size >1
|
||||
content = content.gsub("(#{str1} #{str2})", "(#{s_content} #{str2})")
|
||||
else
|
||||
content = content.gsub("(#{s[0]})", "(#{s_content})")
|
||||
end
|
||||
end
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
|
|
@ -203,7 +213,7 @@ module RepositoriesHelper
|
|||
content = content.gsub("href=\"#{s[0]}\"", "href=\"#{s_content}\"")
|
||||
when 'ss_href_1'
|
||||
content = content.gsub("href=\'#{s[0]}\'", "href=\'#{s_content}\'")
|
||||
else
|
||||
else
|
||||
content = content.gsub("(#{s[0]})", "(#{s_content})")
|
||||
end
|
||||
end
|
||||
|
|
@ -244,7 +254,9 @@ module RepositoriesHelper
|
|||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = entry['content'].present? ? entry['content'] : Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
text = new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
text = "该内容不合规,请修改。" if text.present? && !HarmoniousDictionary.clean?(text)
|
||||
text
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
|
|
@ -253,9 +265,13 @@ module RepositoriesHelper
|
|||
content = entry['content'].present? ? entry['content'] : Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
# Rails.logger.info("content===#{content}")
|
||||
return Base64.decode64(content).force_encoding("GBK").encode("UTF-8") unless Base64.decode64(content).force_encoding('UTF-8').valid_encoding?
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
text = Base64.decode64(content).force_encoding('UTF-8')
|
||||
text = "该内容不合规,请修改。" if text.present? && !HarmoniousDictionary.clean?(text)
|
||||
text
|
||||
elsif entry['is_text_file'] == true
|
||||
return render_decode64_content(entry['content'])
|
||||
text = render_decode64_content(entry['content'])
|
||||
text = "该内容不合规,请修改。" if text.present? && !HarmoniousDictionary.clean?(text)
|
||||
text
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
|
|
@ -264,7 +280,9 @@ module RepositoriesHelper
|
|||
if download_type(file_type)
|
||||
return entry['content']
|
||||
end
|
||||
render_decode64_content(entry['content'])
|
||||
text = render_decode64_content(entry['content'])
|
||||
text = "该内容不合规,请修改。" if text.present? && !HarmoniousDictionary.clean?(text)
|
||||
text
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -305,7 +323,13 @@ module RepositoriesHelper
|
|||
|
||||
def repo_git_submodule_url(owner, repo, path)
|
||||
unless (path.starts_with?('http://') || path.starts_with?('https://'))
|
||||
path = File.expand_path(path, "/#{owner&.login}/#{repo&.identifier}")
|
||||
if path.starts_with?('git@code.gitlink.org.cn')
|
||||
path = path.gsub(":","/").gsub("git@code.gitlink.org.cn","https://gitlink.org.cn")
|
||||
elsif path.starts_with?('git@code.gitlink.org.cn')
|
||||
path = path.gsub(":","/").gsub("git@","https://")
|
||||
else
|
||||
path = File.expand_path(path, "/#{owner&.login}/#{repo&.identifier}")
|
||||
end
|
||||
end
|
||||
|
||||
return path
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
module UserOnline
|
||||
class << self
|
||||
redis_config = YAML.load_file(Rails.root.join('config', 'redis.yml'))
|
||||
if redis_config.present?
|
||||
redis_url = redis_config[Rails.env]['url']
|
||||
$redis = Redis.new({:url=>redis_url})
|
||||
else
|
||||
$redis = Rails.cache.data
|
||||
end
|
||||
def login(user_id)
|
||||
set_bit(user_id, 1)
|
||||
end
|
||||
|
||||
def logout(user_id)
|
||||
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
|
||||
now = Time.now()
|
||||
keys = []
|
||||
(1..5).each do |i|
|
||||
key = (now - i.minutes).strftime("%H-%M")
|
||||
keys << "cache:online_user_#{key}"
|
||||
set_bit_and_expire(cache_key, user_id, 0) unless $redis.ttl(cache_key) == -2
|
||||
end
|
||||
end
|
||||
set_bit(user_id, 0)
|
||||
end
|
||||
|
||||
def set_bit(user_id, flag)
|
||||
if $redis.ttl(cache_key) == -2
|
||||
# 如果key不存在
|
||||
set_bit_and_expire(cache_key, user_id, flag)
|
||||
else
|
||||
if $redis.ttl(cache_key) ==-1
|
||||
# 可以存在,但过期时间没关联
|
||||
# 这种情况大概率是并发原因导致对相应key设置过期时跳过了。所以删除并重新设置过期时间
|
||||
$redis.del(cache_key)
|
||||
set_bit_and_expire(cache_key, user_id, flag)
|
||||
end
|
||||
|
||||
# 统计当前时间下,前5分钟的活跃人数
|
||||
$redis.setbit(cache_key, user_id, flag)
|
||||
end
|
||||
end
|
||||
|
||||
def set_bit_and_expire(cache_key, user_id, flag)
|
||||
$redis.setbit(cache_key, user_id, flag)
|
||||
# $redis.setbit(last_cache_key, user_id, flag)
|
||||
# 现在统计5分钟在线人数,这里设置6分钟过期,目的是统计当前时刻的前5分钟
|
||||
$redis.expire(cache_key, 6 * 60)
|
||||
end
|
||||
|
||||
def count
|
||||
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
|
||||
now = Time.now()
|
||||
keys = []
|
||||
(0..4).each do |i|
|
||||
key = (now - i.minutes).strftime("%H-%M")
|
||||
keys << "cache:online_user_#{key}"
|
||||
end
|
||||
# 防止每个分钟数据有重复,所以去重去除
|
||||
$redis.bitop("OR", "daiao", keys)
|
||||
$redis.bitcount("daiao")
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def cache_key
|
||||
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
|
||||
"cache:online_user_#{Time.now().strftime("%H-%M")}"
|
||||
else
|
||||
raise '请配置config.cache_store = redis_store'
|
||||
end
|
||||
end
|
||||
|
||||
def last_cache_key
|
||||
if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
|
||||
# 如设置5分钟内即300秒有请求的用户视为在线, 则最大会统计到10分钟内有活动用户
|
||||
# TODO 更精确时长
|
||||
begin_hour = Time.now.beginning_of_hour
|
||||
minutes_piece = (Time.now - begin_hour) / (60 * 5)
|
||||
time = begin_hour.since((minutes_piece.to_i - 1) * (60 * 5)).strftime("%H-%M")
|
||||
"cache:online_user_#{time}"
|
||||
else
|
||||
raise '请配置config.cache_store = redis_store'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# remote_ip :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -105,6 +105,24 @@ class Issue < ApplicationRecord
|
|||
scope :pm_includes, -> {includes(:project, :show_issue_tags, :issue_status, :priority, :version, :user, :show_assigners, :comment_journals, :operate_journals)}
|
||||
scope :closed, ->{where(status_id: 5)}
|
||||
scope :opened, ->{where.not(status_id: 5)}
|
||||
scope :with_assigner_info, -> {
|
||||
select("DISTINCT issues.*, u.id AS user_id, CONVERT(COALESCE(u.nickname, u.login) USING gbk) AS user_name").
|
||||
joins("LEFT JOIN (
|
||||
SELECT ia.issue_id, ia.assigner_id
|
||||
FROM issue_assigners ia
|
||||
JOIN (
|
||||
SELECT issue_id, MIN(id) AS min_assigner_id
|
||||
FROM issue_assigners
|
||||
GROUP BY issue_id
|
||||
) tmp ON ia.issue_id = tmp.issue_id AND ia.id = tmp.min_assigner_id
|
||||
) assigner ON issues.id = assigner.issue_id
|
||||
LEFT JOIN users u ON assigner.assigner_id = u.id")
|
||||
}
|
||||
|
||||
scope :ordered_by_assigner, -> (sort_direction) {
|
||||
order("CASE WHEN u.id IS NULL THEN 1 ELSE 0 END ASC")
|
||||
.order("CONVERT(COALESCE(u.nickname, u.login) USING gbk) #{sort_direction}")
|
||||
}
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
before_save :check_pm_and_update_due_date
|
||||
after_save :incre_or_decre_closed_issues_count, :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container, :generate_uuid
|
||||
|
|
@ -124,6 +142,20 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def pm_issue_type_chinese_string
|
||||
case pm_issue_type
|
||||
when 1
|
||||
"需求"
|
||||
when 2
|
||||
"任务"
|
||||
when 3
|
||||
"缺陷"
|
||||
else
|
||||
"疑修"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def destroy_be_pm_links
|
||||
PmLink.where(be_linkable_type:"Issue",be_linkable_id:self.id).map(&:destroy)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class Journal < ApplicationRecord
|
|||
content += "<b>#{self.issue.subject}</b>"
|
||||
else
|
||||
prefix = '将'
|
||||
prefix += "计划" if self.issue.pm_issue_type == 1
|
||||
prefix += "需求" if self.issue.pm_issue_type == 1
|
||||
prefix += "任务" if self.issue.pm_issue_type == 2
|
||||
prefix += "缺陷" if self.issue.pm_issue_type == 3
|
||||
prefix += "<b>#{self.issue.subject}</b>"
|
||||
|
|
@ -358,9 +358,9 @@ class Journal < ApplicationRecord
|
|||
new_value = "未设置" if detail.value.blank?
|
||||
content += "将工作项类型由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
content.gsub!('1', '需求')
|
||||
content.gsub!('2', '任务')
|
||||
content.gsub!('3', '缺陷')
|
||||
content.gsub!('<b>1</b>', '需求')
|
||||
content.gsub!('<b>2</b>', '任务')
|
||||
content.gsub!('<b>3</b>', '缺陷')
|
||||
return content
|
||||
when 'pm_sprint_id'
|
||||
old_value = detail.old_value
|
||||
|
|
@ -483,36 +483,30 @@ class Journal < ApplicationRecord
|
|||
end
|
||||
return content
|
||||
when 'link_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| i.pm_issue_type.nil? && i.pm_project_id.nil? ? "疑修 <b>【#{i.subject}】</b>" : "工作项 <b>[#{i.pm_issue_type_chinese_string}]-<#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| i.pm_issue_type.nil? && i.pm_project_id.nil? ? "疑修 <b>【#{i.subject}】</b>" : "工作项 <b>[#{i.pm_issue_type_chinese_string}]-<#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "新建了关联的工作项#{new_value}"
|
||||
content += "新建了关联的#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "删除了关联的工作项#{old_value}"
|
||||
content += "删除了关联的#{old_value}"
|
||||
else
|
||||
content += "新建了关联的工作项#{new_value}"
|
||||
content += "新建了关联的#{new_value}"
|
||||
end
|
||||
end
|
||||
content.gsub!('1', "需求")
|
||||
content.gsub!('2', "任务")
|
||||
content.gsub!('3', "缺陷")
|
||||
return content
|
||||
when 'tag_link_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| i.pm_issue_type.nil? && i.pm_project_id.nil? ? "疑修 <b>【#{i.subject}】</b>" : "工作项 <b>[#{i.pm_issue_type_chinese_string}]-<#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| i.pm_issue_type.nil? && i.pm_project_id.nil? ? "疑修 <b>【#{i.subject}】</b>" : "工作项 <b>[#{i.pm_issue_type_chinese_string}]-<#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了工作项#{new_value}"
|
||||
content += "关联了#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的工作项#{old_value}"
|
||||
content += "取消了关联的#{old_value}"
|
||||
else
|
||||
content += "关联了工作项#{new_value}"
|
||||
content += "关联了#{new_value}"
|
||||
end
|
||||
end
|
||||
content.gsub!('1', "需求")
|
||||
content.gsub!('2', "任务")
|
||||
content.gsub!('3', "缺陷")
|
||||
return content
|
||||
when 'issue'
|
||||
issue = self.issue
|
||||
|
|
@ -535,6 +529,7 @@ class Journal < ApplicationRecord
|
|||
case detail.property
|
||||
when 'issue'
|
||||
content += "创建了<b>疑修</b>"
|
||||
return content
|
||||
when 'attachment'
|
||||
old_value = Attachment.where("BINARY id in (?) or uuid in (?)", detail.old_value.to_s.split(","), detail.old_value.to_s.split(",")).pluck(:filename).join("、")
|
||||
new_value = Attachment.where("BINARY id in (?) or uuid in (?)", detail.value.to_s.split(","), detail.value.to_s.split(",")).pluck(:filename).join("、")
|
||||
|
|
@ -544,6 +539,7 @@ class Journal < ApplicationRecord
|
|||
new_value = "无" if new_value.blank?
|
||||
content += "将附件由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
return content
|
||||
when 'issue_tag'
|
||||
old_value = IssueTag.where(id: detail.old_value.split(",")).pluck(:name).join("、")
|
||||
new_value = IssueTag.where(id: detail.value.split(",")).pluck(:name).join("、")
|
||||
|
|
@ -553,6 +549,7 @@ class Journal < ApplicationRecord
|
|||
new_value = "无" if new_value.blank?
|
||||
content += "将标记由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
return content
|
||||
when 'assigner'
|
||||
old_value = User.where(id: detail.old_value.split(",")).map{|u| u.real_name}.join("、")
|
||||
new_value = User.where(id: detail.value.split(",")).map{|u| u.real_name}.join("、")
|
||||
|
|
@ -562,6 +559,7 @@ class Journal < ApplicationRecord
|
|||
new_value = "无" if new_value.blank?
|
||||
content += "将负责人由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
return content
|
||||
when 'attr'
|
||||
content += "将"
|
||||
case detail.prop_key
|
||||
|
|
@ -604,8 +602,9 @@ class Journal < ApplicationRecord
|
|||
new_value = "无" if new_value.blank?
|
||||
content += "由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
content = self.pm_operate_content if content == ""
|
||||
end
|
||||
|
||||
def journal_content
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class Laboratory < ApplicationRecord
|
|||
|
||||
validates :identifier, uniqueness: { case_sensitive: false }, allow_nil: true
|
||||
|
||||
delegate :name, :navbar, :footer, :login_logo_url, :nav_logo_url, :tab_logo_url, :default_navbar, to: :laboratory_setting
|
||||
delegate :name, :navbar, :footer, :login_logo_url, :nav_logo_url, :pm_logo_url, :tab_logo_url, :default_navbar, to: :laboratory_setting
|
||||
|
||||
def site
|
||||
rails_env = EduSetting.get('rails_env')
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ class LaboratorySetting < ApplicationRecord
|
|||
def nav_logo_url
|
||||
image_url('nav')
|
||||
end
|
||||
|
||||
def pm_logo_url
|
||||
image_url('pm_logo')
|
||||
end
|
||||
def tab_logo_url
|
||||
image_url('tab')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
class ProjectAction < ApplicationRecord
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :user, optional: true
|
||||
|
||||
serialize :event_extra, Hash
|
||||
end
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
|
||||
class ProjectActions::ForkEvent < ProjectAction
|
||||
def self.build(project, user, fork_project)
|
||||
project_action = new(project: project, user: user)
|
||||
project_action.event_extra = {
|
||||
forkee_id: fork_project.id,
|
||||
forkee_name: fork_project.identifier,
|
||||
forkee_owner_id: fork_project.owner.id,
|
||||
forkee_owner_login: fork_project.owner.login
|
||||
}.as_json
|
||||
project_action.save!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
|
||||
class ProjectActions::IssueCommentEvent < ProjectAction
|
||||
def self.build(project, user, issue, journal)
|
||||
project_action = new(project: project, user: user)
|
||||
project_action.event_extra = {
|
||||
issue_id: issue.id,
|
||||
issue_number: issue.project_issues_index,
|
||||
body: journal.notes
|
||||
}.as_json
|
||||
project_action.save!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
|
||||
class ProjectActions::IssuesEvent < ProjectAction
|
||||
def self.build(project, user, issue, action)
|
||||
project_action = new(project: project, user: user)
|
||||
project_action.event_extra = {
|
||||
issue_id: issue.id,
|
||||
issue_number: issue.project_issues_index,
|
||||
issue_author_id: issue.author_id,
|
||||
issue_author_login: issue.user.login,
|
||||
title: issue.subject,
|
||||
body: issue.description,
|
||||
action: action
|
||||
}.as_json
|
||||
project_action.save!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
|
||||
class ProjectActions::PullRequestEvent < ProjectAction
|
||||
def self.build(project, user, pull_request, action)
|
||||
project_action = new(project: project, user: user)
|
||||
gitea_pull_request = Gitea::PullRequest::FilesService.call(project.owner.login, project.identifier, pull_request.gitea_number, project&.owner&.gitea_token)
|
||||
project_action.event_extra = {
|
||||
action: action,
|
||||
pull_id: pull_request.id,
|
||||
pull_number: pull_request.gitea_number,
|
||||
title: pull_request.title,
|
||||
# body: pull_request.body,
|
||||
# git_diff: gitea_pull_request,
|
||||
additions: gitea_pull_request['TotalAddition'],
|
||||
deletions: gitea_pull_request['TotalDeletion'],
|
||||
changed_files: gitea_pull_request['NumFiles'],
|
||||
merged: pull_request.status == 1,
|
||||
base_ref: pull_request.base,
|
||||
head_repo_id: pull_request.is_original ? pull_request.fork_project_id : pull_request.project_id,
|
||||
head_repo_name: pull_request.project&.identifier,
|
||||
head_ref: pull_request.head
|
||||
}.as_json
|
||||
project_action.save!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
|
||||
class ProjectActions::PullRequestReviewCommentEvent < ProjectAction
|
||||
def self.build(project, user, pull_request, journal)
|
||||
project_action = new(project: project, user: user)
|
||||
project_action.event_extra = {
|
||||
pull_id: pull_request.id,
|
||||
pull_number: pull_request.gitea_number,
|
||||
body: journal.notes
|
||||
}.as_json
|
||||
project_action.save!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
|
||||
class ProjectActions::ReleaseEvent < ProjectAction
|
||||
def self.build(project, user, version_release)
|
||||
project_action = new(project: project, user: user)
|
||||
project_action.event_extra = {
|
||||
tag_name: version_release.tag_name,
|
||||
name: version_release.name,
|
||||
body: version_release.body
|
||||
}.as_json
|
||||
project_action.save!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# type :string(255)
|
||||
# user_id :integer
|
||||
# event_extra :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_actions_on_project_id (project_id)
|
||||
#
|
||||
|
||||
class ProjectActions::StarEvent < ProjectAction
|
||||
def self.build(project, user)
|
||||
project_action = new(project: project, user: user)
|
||||
project_action.save!
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -144,6 +144,18 @@ class PullRequest < ApplicationRecord
|
|||
"#{Rails.application.config_for(:configuration)['platform_url']}/#{self.project.owner.login}/#{self.project.name}/pulls/#{self.id}"
|
||||
end
|
||||
|
||||
def closed?
|
||||
self.status == CLOSED
|
||||
end
|
||||
|
||||
def merged?
|
||||
self.status == MERGED
|
||||
end
|
||||
|
||||
def opened?
|
||||
self.status == OPEN
|
||||
end
|
||||
|
||||
def pr_status
|
||||
case status
|
||||
when 0
|
||||
|
|
|
|||
|
|
@ -25,17 +25,20 @@
|
|||
|
||||
class UserAction < ApplicationRecord
|
||||
|
||||
belongs_to :user, optional: true
|
||||
|
||||
after_save :add_user_info
|
||||
|
||||
serialize :data_bank, JSON
|
||||
|
||||
def action_name
|
||||
case action_type
|
||||
when "DestroyUser" then "用户注销"
|
||||
when "DestroyUser" then "删除用户"
|
||||
when "DestroyProject" then "删除项目"
|
||||
when "Login" then "登录"
|
||||
when "Logout" then "退出登录"
|
||||
when "DestroyOrganization" then "删除组织"
|
||||
when "Attachment" then "上传附件"
|
||||
else self.action_type
|
||||
end
|
||||
end
|
||||
|
|
@ -43,7 +46,7 @@ class UserAction < ApplicationRecord
|
|||
def opt_user_name
|
||||
user = User.find_by(id: self.user_id)
|
||||
if user.present?
|
||||
user&.login
|
||||
user&.real_name
|
||||
else
|
||||
del_user = UserAction.find_by(action_type: "DestroyUser", action_id: self.user_id)
|
||||
del_user.present? ? del_user.user.login : "不存在用户:#{user_id}"
|
||||
|
|
@ -55,6 +58,13 @@ class UserAction < ApplicationRecord
|
|||
when "DestroyUser" then "账号:#{user&.login}<br/>邮箱:#{user&.mail}<br/>手机号:#{user&.phone}<br/>昵称:#{user&.nickname}<br/>"
|
||||
when "DestroyProject" then "项目名称:#{project&.name}<br/>项目标识:#{project&.identifier}<br/>"
|
||||
when "DestroyOrganization" then "组织名称:#{organization&.nickname}<br/>组织标识:#{organization&.login}<br/>"
|
||||
when 'Attachment'
|
||||
issue = Issue.find_by_id(attachment.container_id)
|
||||
if attachment.container_type == "Issue" && issue&.issue_classify == "issue"
|
||||
return "上传附件issue地址:<a href=\"#{Rails.application.config_for(:configuration)['platform_url']}/#{issue&.project&.owner&.login}/#{issue&.project&.identifier}/issues/#{issue&.project_issues_index}\">#{issue&.subject}</a>"
|
||||
else
|
||||
return "上传附件地址:<a href=\"#{Rails.application.config_for(:configuration)['platform_url']}/attachments/#{attachment.uuid}\">#{attachment.title}</a>"
|
||||
end
|
||||
else "--"
|
||||
end
|
||||
end
|
||||
|
|
@ -86,6 +96,15 @@ class UserAction < ApplicationRecord
|
|||
action_organization
|
||||
end
|
||||
|
||||
def attachment
|
||||
action_attachment = if action_type == "Attachment" && data_bank.present?
|
||||
build_mode("Attachment")
|
||||
else
|
||||
Attachment.find_by(id: self.action_id)
|
||||
end
|
||||
action_attachment
|
||||
end
|
||||
|
||||
|
||||
def build_mode(model_name)
|
||||
model = model_name.constantize.new
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class Admins::SaveLaboratorySettingService < ApplicationService
|
|||
save_image_file(params[:nav_logo], 'nav')
|
||||
save_image_file(params[:login_logo], 'login')
|
||||
save_image_file(params[:tab_logo], 'tab')
|
||||
save_image_file(params[:pm_logo], 'pm_logo')
|
||||
save_image_file(params[:subject_banner], '_subject_banner')
|
||||
save_image_file(params[:course_banner], '_course_banner')
|
||||
save_image_file(params[:competition_banner], '_competition_banner')
|
||||
|
|
|
|||
|
|
@ -97,6 +97,9 @@ class Api::V1::Issues::CreateService < ApplicationService
|
|||
# @信息发送
|
||||
AtmeService.call(current_user, @atme_receivers, @created_issue) unless receivers_login.blank?
|
||||
|
||||
# 项目行为构建
|
||||
ProjectActions::IssuesEvent.build(@project, current_user, @created_issue, 'opened')
|
||||
|
||||
# 发消息
|
||||
if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @created_issue&.id, assigner_ids) unless assigner_ids.blank?
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Api::V1::Issues::Journals::CreateService < ApplicationService
|
|||
@issue.save!
|
||||
|
||||
push_activity_2_blockchain("issue_comment_create", @created_journal) if Site.has_blockchain? && @issue.project&.use_blockchain
|
||||
|
||||
ProjectActions::IssueCommentEvent.build(@issue.project, current_user, @issue, @created_journal)
|
||||
# @信息发送
|
||||
AtmeService.call(current_user, @atme_receivers, @created_journal) unless receivers_login.blank?
|
||||
TouchWebhookJob.set(wait: 5.seconds).perform_later('IssueComment', @issue&.id, @current_user.id, @created_journal.id, 'created', {})
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class Api::V1::Issues::ListService < ApplicationService
|
|||
|
||||
validates :category, inclusion: { in: %w[all opened closed], message: '请输入正确的Category'}
|
||||
validates :participant_category, inclusion: { in: %w[all aboutme authoredme assignedme atme], message: '请输入正确的ParticipantCategory'}
|
||||
validates :sort_by, inclusion: { in: %w[issues.created_on issues.updated_on issues.blockchain_token_num issue_priorities.position issues.start_date issues.due_date issues.status_id] , message: '请输入正确的SortBy'}, allow_blank: true
|
||||
validates :sort_by, inclusion: { in: %w[issues.created_on issues.updated_on issues.blockchain_token_num issue_priorities.position issues.start_date issues.due_date issues.status_id, assigners] , message: '请输入正确的SortBy'}, allow_blank: true
|
||||
validates :sort_direction, inclusion: { in: %w[asc desc], message: '请输入正确的SortDirection'}, allow_blank: true
|
||||
validates :current_user, presence: true
|
||||
|
||||
|
|
@ -175,6 +175,8 @@ class Api::V1::Issues::ListService < ApplicationService
|
|||
scope = issues.includes(:priority, :issue_status, :user, :show_assigners, :show_issue_tags, :version, :comment_journals)
|
||||
scope = if sort_by == 'issue_priorities.position'
|
||||
scope.reorder("issue_priorities.position #{sort_direction}, issues.updated_on DESC").distinct
|
||||
elsif sort_by == 'assigners'
|
||||
scope.with_assigner_info.ordered_by_assigner(sort_direction)
|
||||
else
|
||||
scope.reorder("#{sort_by} #{sort_direction}").distinct
|
||||
end
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
build_after_issue_journal_details if @updated_issue.previous_changes.present? # 操作记录
|
||||
build_previous_issue_changes
|
||||
build_issue_project_trends if status_id.present? # 开关时间记录
|
||||
build_project_actions
|
||||
build_cirle_blockchain_token if blockchain_token_num.present?
|
||||
unless @project.id.zero?
|
||||
# @信息发送
|
||||
|
|
@ -185,6 +186,15 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
end
|
||||
end
|
||||
|
||||
def build_project_actions
|
||||
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][1] == 5
|
||||
ProjectActions::IssuesEvent.build(@project, current_user, @updated_issue, 'closed')
|
||||
end
|
||||
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][0] == 5
|
||||
ProjectActions::IssuesEvent.build(@project, current_user, @updated_issue, 'reopened')
|
||||
end
|
||||
end
|
||||
|
||||
def build_after_issue_journal_details
|
||||
begin
|
||||
# 更改标题
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ class Api::V1::Projects::Commits::RecentService < ApplicationService
|
|||
param = {
|
||||
access_token: token,
|
||||
page: page,
|
||||
limit: limit
|
||||
limit: limit,
|
||||
stats: false,
|
||||
files: false
|
||||
}
|
||||
param.merge!(keyword: keyword) if keyword.present?
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
class Api::V1::Projects::Pulls::ReopenService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :pull_request, :issue, :user
|
||||
|
||||
|
||||
def initialize(project, pull_request, user)
|
||||
@project = project
|
||||
@pull_request = pull_request
|
||||
@issue = pull_request&.issue
|
||||
@user = user
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, "参数错误" unless valid?
|
||||
if gitea_change_status
|
||||
@pull_request.update_column(:status, PullRequest::OPEN)
|
||||
@pull_request&.project_trends&.where(action_type: ProjectTrend::CLOSE).destroy_all
|
||||
@issue.update_column(:status_id, IssueStatus::ADD)
|
||||
|
||||
return true
|
||||
else
|
||||
raise Error, 'gitea change status failed'
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def valid?
|
||||
return false if @project.blank? || @pull_request.blank? || @issue.blank? || @user.blank?
|
||||
return false unless @pull_request.closed?
|
||||
return true
|
||||
end
|
||||
|
||||
def gitea_change_status
|
||||
gitea_result = Gitea::PullRequest::ChangeStatusService.call(@project.owner.login, @project.identifier, @pull_request.gitea_number, false, @user&.gitea_token)
|
||||
return true if gitea_result[:status] == :success
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
class Api::V1::Users::Feedbacks::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :user, :content
|
||||
attr_reader :user, :content, :remote_ip
|
||||
attr_accessor :feedback
|
||||
|
||||
validates :content, presence: true
|
||||
|
||||
def initialize(user, params)
|
||||
def initialize(user, params, remote_ip="127.0.0.1")
|
||||
@user = user
|
||||
@content = params[:content]
|
||||
@remote_ip = remote_ip
|
||||
end
|
||||
|
||||
def call
|
||||
|
|
@ -16,6 +17,7 @@ class Api::V1::Users::Feedbacks::CreateService < ApplicationService
|
|||
|
||||
begin
|
||||
@feedback = Feedback.new(user: user, content: content)
|
||||
@feedback.remote_ip = @remote_ip
|
||||
@feedback.save!
|
||||
|
||||
return @feedback.valid? ? @feedback : nil
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
# Get a pull request
|
||||
class Gitea::PullRequest::ChangeStatusService < Gitea::ClientService
|
||||
attr_reader :owner, :repo, :number, :is_closed, :token
|
||||
|
||||
#eq:
|
||||
# Gitea::PullRequest::ChangeStatusService.call(user.login, repository.identifier, pull.gitea_number, true, user.gitea_token)
|
||||
def initialize(owner, repo, number, is_closed, token=nil)
|
||||
@owner = owner
|
||||
@repo = repo
|
||||
@number = number
|
||||
@is_closed = is_closed
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
response = get(url, request_params, true)
|
||||
status, message, body = render_response(response)
|
||||
json_format(status, message, body)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request_params
|
||||
Hash.new.merge(token: token, is_closed: is_closed)
|
||||
end
|
||||
|
||||
def url
|
||||
"/repos/#{owner}/#{repo}/pulls/#{number}/change_status".freeze
|
||||
end
|
||||
|
||||
def json_format(status, message, body)
|
||||
case status
|
||||
when 204 then success(body)
|
||||
else
|
||||
error(message, status)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -39,7 +39,8 @@ class Projects::ForkService < ApplicationService
|
|||
|
||||
ForkUser.create(project_id: @project.id, fork_project_id: clone_project.id, user_id: clone_project.user_id)
|
||||
SendTemplateMessageJob.perform_later('ProjectForked', @target_owner.id, @project.id) if Site.has_notice_menu?
|
||||
|
||||
ProjectActions::ForkEvent.build(@project, @target_owner, clone_project)
|
||||
|
||||
clone_project
|
||||
end
|
||||
rescue => e
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class Repositories::CreateService < ApplicationService
|
|||
begin
|
||||
@gitea_repository = $gitea_client.get_repos_by_owner_repo(project.owner.login, params[:identifier])
|
||||
rescue Gitea::Api::ServerError => e
|
||||
if e.http_code.to_i == 404
|
||||
if e.http_code.to_i == 404 || e.http_code.to_i == 307
|
||||
if project.owner.is_a?(User)
|
||||
# @gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call
|
||||
@gitea_repository = $gitea_client.post_user_repos({query: {token: user.gitea_token}, body: gitea_repository_params.to_json})
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<% add_admin_breadcrumb('概览', admins_path) %>
|
||||
<% end %>
|
||||
|
||||
<% cache "/admin/dashboards/#{Time.now.strftime('%Y-%m-%d')}", :expires_in => 1.days do %>
|
||||
<%# cache_if EduSetting.get("open_baidu_tongji").to_s == "true", "/admin/dashboards/#{Time.now.strftime('%Y-%m-%d')}", :expires_in => 1.days do %>
|
||||
<div class="header bg-gradient-primary pb-8 pt-md-8">
|
||||
<div class="container-fluid">
|
||||
<div class="header-body">
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%end %>
|
||||
<%#end %>
|
||||
|
||||
<div class="box admin-list-container project-language-list-container">
|
||||
<table class="table table-hover text-center subject-list-table">
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@
|
|||
<th width="5%">序号</th>
|
||||
<th width="10%">用户名</th>
|
||||
<th width="20%">用户邮箱</th>
|
||||
<th width="20%">ip地址</th>
|
||||
<th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_feedbacks_path) %></th>
|
||||
<th width="25%">反馈意见</th>
|
||||
<th width="15%">操作</th>
|
||||
<!-- 这里是注释内容
|
||||
<th width="15%">操作</th>
|
||||
-->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -16,14 +19,17 @@
|
|||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= feedback&.user&.login%></td>
|
||||
<td><%= feedback&.user&.mail%></td>
|
||||
<td><%= feedback&.remote_ip%></td>
|
||||
<td><%= feedback.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td style="word-wrap: break-word;">
|
||||
<%= feedback.content %>
|
||||
</td>
|
||||
<!-- 这里是注释内容
|
||||
<td class="action-container">
|
||||
<%= link_to "发送邮件", new_history_admins_feedback_path(feedback), remote: true, class: "action" %>
|
||||
<%#= link_to "发送邮件", new_history_admins_feedback_path(feedback), remote: true, class: "action" %>
|
||||
<%#= link_to "删除", admins_feedback_path(feedback), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
|
||||
</td>
|
||||
-->
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
<div class="setting-item-head"><h6>Logo设置</h6></div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="pl-0 py-3 row setting-item-body">
|
||||
<div class="col-12 col-md-4 logo-item">
|
||||
<div class="col-12 col-md-3 logo-item">
|
||||
<% nav_logo_img = setting.nav_logo_url %>
|
||||
<div class="logo-item-left mr-3 <%= nav_logo_img ? 'has-img' : '' %>">
|
||||
<img class="logo-item-img nav-logo-img" src="<%= nav_logo_img %>" style="<%= nav_logo_img.present? ? '' : 'display: none' %>"/>
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4 logo-item">
|
||||
<div class="col-12 col-md-3 logo-item">
|
||||
<% login_logo_img = setting.login_logo_url %>
|
||||
<div class="logo-item-left mr-3 <%= login_logo_img ? 'has-img' : '' %>">
|
||||
<img class="logo-item-img login-logo-img" src="<%= login_logo_img %>" style="<%= login_logo_img.present? ? '' : 'display: none' %>"/>
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4 logo-item">
|
||||
<div class="col-12 col-md-3 logo-item">
|
||||
<% tab_logo_img = setting.tab_logo_url %>
|
||||
<div class="logo-item-left mr-3 <%= tab_logo_img ? 'has-img' : '' %>">
|
||||
<img class="logo-item-img tab-logo-img" src="<%= tab_logo_img %>" style="<%= tab_logo_img.present? ? '' : 'display: none' %>"/>
|
||||
|
|
@ -83,6 +83,21 @@
|
|||
<div>尺寸:16*16 32*32 48*48 64*64 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-3 logo-item">
|
||||
<% pm_logo_img = setting.pm_logo_url %>
|
||||
<div class="logo-item-left mr-3 <%= pm_logo_img ? 'has-img' : '' %>">
|
||||
<img class="logo-item-img tab-logo-img" src="<%= pm_logo_img %>" style="<%= tab_logo_img.present? ? '' : 'display: none' %>"/>
|
||||
<%= file_field_tag(:pm_logo, accept: 'image/png,image/jpg,image/jpeg', style: 'display: none', value: params[:pm_logo]) %>
|
||||
<label for="pm_logo" class="logo-item-upload" data-toggle="tooltip" data-title="选择图片"></label>
|
||||
</div>
|
||||
<div class="logo-item-right">
|
||||
<div class="logo-item-title flex-1">PM管理端logo</div>
|
||||
<div>格式:PNG、JPG</div>
|
||||
<div>尺寸:高度90px以内,宽等比例缩放</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs', has_permission: current_user.admin? || current_user.business?) %></li>
|
||||
<li><%= sidebar_item(admins_nps_path, 'NPS用户调研', icon: 'question-circle', controller: 'admins-nps', has_permission: current_user.admin? || current_user.business?) %></li>
|
||||
<li><%= sidebar_item(admins_feedbacks_path, '用户反馈', icon: 'question-circle', controller: 'admins-feedbacks', has_permission: current_user.admin? || current_user.business?) %></li>
|
||||
<li><%= sidebar_item(admins_user_actions_path, '操作记录', icon: 'pencil-square', controller: 'admins-user_actions', has_permission: current_user.admin?) %></li>
|
||||
<li><%= sidebar_item(admins_user_actions_path, '操作日志', icon: 'pencil-square', controller: 'admins-user_actions', has_permission: current_user.admin?) %></li>
|
||||
<li><%= sidebar_item(admins_system_notifications_path, '系统公告配置', icon: 'bell', controller: 'admins-system_notifications', has_permission: current_user.admin? || current_user.business?) %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
<div class="box search-form-container user-list-form">
|
||||
<%= form_tag(admins_user_actions_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
|
||||
操作类型:
|
||||
<% action_type_options = [['自定义',''],['用户注销','DestroyUser'], ['删除项目', 'DestroyProject'], ['删除组织', 'DestroyOrganization']] %>
|
||||
<% action_type_options = [['上传附件', 'Attachment'], ['登录', 'Login'], ['退出登录', 'Logout'],['删除用户','DestroyUser'], ['删除项目', 'DestroyProject'], ['删除组织', 'DestroyOrganization']] %>
|
||||
<%= select_tag(:action_type_select, options_for_select(action_type_options), class: 'form-control') %>
|
||||
<%= text_field_tag(:action_type, params[:action_type], class: 'form-control col-sm-2 ml-3',style: 'display:;', placeholder: '自定义操作类型检索') %>
|
||||
<%= text_field_tag(:action_type, params[:action_type], class: 'form-control col-sm-2 ml-3',style: 'display: none;', placeholder: '自定义操作类型检索') %>
|
||||
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '操作人用户名/邮箱/手机号检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
json.(issue, :id, :subject, :project_issues_index)
|
||||
json.blockchain_token_num (Site.has_blockchain? && issue.project&.use_blockchain) ? issue.blockchain_token_num : nil
|
||||
json.created_at issue.created_on.strftime("%Y-%m-%d %H:%M")
|
||||
json.updated_at issue.updated_on.strftime("%Y-%m-%d %H:%M")
|
||||
json.tags issue.show_issue_tags.each do |tag|
|
||||
json.partial! "api/v1/issues/issue_tags/simple_detail", locals: {tag: tag}
|
||||
end
|
||||
json.status_name issue.issue_status&.name
|
||||
json.status_id issue.status_id
|
||||
json.status do
|
||||
if issue.issue_status.present?
|
||||
json.partial! "api/v1/issues/statues/simple_detail", locals: {status: issue.issue_status}
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
end
|
||||
json.priority_name issue.priority&.name
|
||||
json.priority_id issue.priority_id
|
||||
json.priority do
|
||||
if issue.priority.present?
|
||||
json.partial! "api/v1/issues/issue_priorities/simple_detail", locals: {priority: issue.priority}
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
end
|
||||
json.milestone_name issue.version&.name
|
||||
json.milestone_id issue.fixed_version_id
|
||||
json.root_id issue.root_id
|
||||
json.pm_issue_type issue.pm_issue_type
|
||||
json.pm_sprint_id issue.pm_sprint_id
|
||||
json.pm_project_id issue.pm_project_id
|
||||
json.time_scale issue.time_scale
|
||||
if weekly_begin_date.present? && weekly_end_date.present?
|
||||
if params[:pm_issue_types].present?
|
||||
json.child_count issue.children_issues.where(pm_issue_type: 4).where("due_date >=? and start_date <=?", weekly_begin_date, weekly_end_date).count
|
||||
else
|
||||
json.child_count issue.children_issues.where("due_date >=? and start_date <=?", weekly_begin_date, weekly_end_date).count
|
||||
end
|
||||
else
|
||||
if params[:pm_issue_types].present?
|
||||
json.child_count issue.children_issues.where(pm_issue_type: 4).count
|
||||
else
|
||||
json.child_count issue.child_count
|
||||
end
|
||||
end
|
||||
|
||||
json.author do
|
||||
json.partial! "api/v1/users/simple_user", locals: {user: issue.user}
|
||||
end
|
||||
json.assigners issue.show_assigners.each do |assigner|
|
||||
json.partial! "api/v1/users/simple_user", locals: {user: assigner}
|
||||
end
|
||||
json.comment_journals_count issue.comment_journals.size
|
||||
json.start_date issue.start_date
|
||||
json.due_date issue.due_date
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
json.this_week_all_issues @this_week_all_issues.each do |issue|
|
||||
json.partial! "api/v1/issues/simple_detail", locals: {issue: issue}
|
||||
json.partial! "api/pm/weekly_issues/simple_detail", locals: {issue: issue, weekly_begin_date: @weekly_begin_date, weekly_end_date: @weekly_end_date}
|
||||
end
|
||||
json.this_week_total_count @this_week_all_issues.total_count
|
||||
json.next_week_all_issues @next_week_all_issues.each do |issue|
|
||||
json.partial! "api/v1/issues/simple_detail", locals: {issue: issue}
|
||||
json.partial! "api/pm/weekly_issues/simple_detail", locals: {issue: issue, weekly_begin_date: @weekly_begin_date.to_date+1.week, weekly_end_date: @weekly_end_date.to_date+1.week}
|
||||
end
|
||||
json.next_week_total_count @next_week_all_issues.total_count
|
||||
|
|
@ -1,4 +1,11 @@
|
|||
json.(issue, :id, :subject, :project_issues_index)
|
||||
json.(issue, :id, :subject, :project_issues_index, :project_id)
|
||||
json.project do
|
||||
if issue.project.present?
|
||||
json.partial! "api/v1/projects/simple_detail", locals: {project: issue.project}
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
end
|
||||
json.blockchain_token_num (Site.has_blockchain? && issue.project&.use_blockchain) ? issue.blockchain_token_num : nil
|
||||
json.created_at issue.created_on.strftime("%Y-%m-%d %H:%M")
|
||||
json.updated_at issue.updated_on.strftime("%Y-%m-%d %H:%M")
|
||||
|
|
@ -35,7 +42,6 @@ if params[:pm_issue_types].present?
|
|||
else
|
||||
json.child_count issue.child_count
|
||||
end
|
||||
|
||||
json.author do
|
||||
json.partial! "api/v1/users/simple_user", locals: {user: issue.user}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ end
|
|||
if journal.is_journal_detail?
|
||||
detail = journal.journal_details.take
|
||||
json.operate_category @issue.pm_issue_type.nil? ? detail.property == "attr" ? detail.prop_key : detail.property : journal.pm_operate_category
|
||||
json.operate_content journal.is_journal_detail? ? @issue.pm_issue_type.nil? ? journal.operate_content : journal.pm_operate_content : nil
|
||||
json.operate_content journal.is_journal_detail? ? @issue.pm_project_id.nil? && @issue.pm_issue_type.nil? ? journal.operate_content : journal.pm_operate_content : nil
|
||||
else
|
||||
json.notes journal.notes
|
||||
json.comments_count journal.comments_count
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
json.total_count @projects.total_count
|
||||
json.projects @projects.each do |project|
|
||||
json.(project, :id, :name, :identifier, :description, :forked_count, :praises_count, :forked_from_project_id, :is_public)
|
||||
json.mirror_url project.repository&.mirror_url
|
||||
json.type project.numerical_for_project_type
|
||||
json.praised project.praised_by?(current_user)
|
||||
json.last_update_time render_unix_time(project.updated_on)
|
||||
json.full_last_update_time project.updated_on
|
||||
json.time_ago time_from_now(project.updated_on)
|
||||
json.language do
|
||||
if project.project_language.blank?
|
||||
json.nil!
|
||||
else
|
||||
json.id project.project_language.id
|
||||
json.name project.project_language.name
|
||||
end
|
||||
end
|
||||
json.category do
|
||||
if project.project_category.blank?
|
||||
json.nil!
|
||||
else
|
||||
json.id project.project_category.id
|
||||
json.name project.project_category.name
|
||||
end
|
||||
end
|
||||
json.topics project.project_topics.each do |topic|
|
||||
json.(topic, :id, :name)
|
||||
end
|
||||
json.url project.full_url
|
||||
json.owner do
|
||||
json.partial! "api/v1/users/simple_user", locals: {user: @organization.team_users.joins(:team).where(teams: {authorize: "owner"}).take&.user}
|
||||
end
|
||||
json.team_users_count @organization.team_users.size
|
||||
end
|
||||
|
|
@ -19,6 +19,7 @@ on:
|
|||
<% end %>
|
||||
<%if node.name.to_s.include?("on-pull_request") %>
|
||||
pull_request:
|
||||
types: [opened, reopened]
|
||||
<% end %>
|
||||
<%if node.name.to_s.include?("on-fork") %>
|
||||
fork:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ elsif @owner.present? && @owner.is_a?(User)
|
|||
json.undo_events @undo_events
|
||||
json.user_composes_count @user_composes_count
|
||||
json.user_org_count @user_org_count
|
||||
json.user_project_count @user_projects_count
|
||||
json.common_projects_count @projects_common_count
|
||||
json.mirror_projects_count @projects_mirrior_count
|
||||
json.sync_mirror_projects_count @projects_sync_mirrior_count
|
||||
|
|
|
|||
|
|
@ -30,4 +30,6 @@ json.praises project_common["praises"]
|
|||
json.issues project_common["issues"]
|
||||
json.pulls project_common["pullrequests"]
|
||||
json.commits project_common["commits"]
|
||||
json.issues project_common["issues"]
|
||||
json.issues project_common["issues"]
|
||||
json.website project_common['website']
|
||||
json.lesson_url project_common['project.lesson_url']
|
||||
|
|
@ -31,7 +31,7 @@ json.author do
|
|||
json.name user.try(:show_real_name)
|
||||
json.type user&.type
|
||||
json.login user.login
|
||||
json.image_url url_to_avatar(user)
|
||||
json.image_url url_to_avatar(user).present? ? url_to_avatar(user) : User::Avatar.get_letter_avatar_url(user.login)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ json.projects @projects do |project|
|
|||
json.time_ago time_from_now(project.updated_on)
|
||||
json.forked_from_project_id project.forked_from_project_id
|
||||
json.open_devops project.open_devops?
|
||||
json.website project.website
|
||||
json.lesson_url project.lesson_url
|
||||
json.platform project.platform
|
||||
json.has_dataset project.has_menu_permission("dataset") && project.project_dataset.present?
|
||||
json.author do
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ json.commits_count @gitea_pull["commit_num"]
|
|||
json.files_count @gitea_pull["changed_files"]
|
||||
json.comments_count @issue.journals.parent_journals.size
|
||||
json.comments_total_count @issue.get_journals_size
|
||||
json.can_reopen @pull_request.closed?
|
||||
json.assign_user do
|
||||
json.partial! 'users/user_simple', user: @issue_assign_to
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ json.setting do
|
|||
json.name default_setting.name
|
||||
json.nav_logo_url default_setting.nav_logo_url&.[](1..-1)
|
||||
json.login_logo_url default_setting.login_logo_url&.[](1..-1)
|
||||
json.pm_logo_url default_setting.pm_logo_url&.[](1..-1)
|
||||
json.tab_logo_url default_setting.tab_logo_url.present? ? default_setting.tab_logo_url&.[](1..-1) : "favicon.ico"
|
||||
json.site_page_deploy_domain @deploy_domain
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ json.user_id @user.id
|
|||
json.image_url url_to_avatar(@user)
|
||||
json.admin @user.admin
|
||||
json.email @user.mail
|
||||
json.phone @user.phone
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ json.undo_join_projects @common_applied_projects.size
|
|||
json.undo_events @undo_events
|
||||
json.user_composes_count @user_composes_count
|
||||
json.user_org_count @user_org_count
|
||||
json.user_projects_count @user_projects_count
|
||||
json.common_projects_count @projects_common_count
|
||||
json.mirror_projects_count @projects_mirrior_count
|
||||
json.sync_mirror_projects_count @projects_sync_mirrior_count
|
||||
|
|
|
|||
|
|
@ -1,37 +1,4 @@
|
|||
习近平
|
||||
习仲勋
|
||||
贺国强
|
||||
贺子珍
|
||||
周永康
|
||||
李德生
|
||||
王岐山
|
||||
姚依林
|
||||
回良玉
|
||||
李源潮
|
||||
李干成
|
||||
戴秉国
|
||||
刘延东
|
||||
刘瑞龙
|
||||
俞正声
|
||||
薄熙来
|
||||
薄一波
|
||||
周小川
|
||||
周建南
|
||||
温云松
|
||||
江绵康
|
||||
李小鹏
|
||||
李小琳
|
||||
朱云来
|
||||
让国人愤怒的第二代身份证
|
||||
文化大革命
|
||||
胡海峰
|
||||
陈良宇
|
||||
老丁
|
||||
莱仕德事件
|
||||
fuck
|
||||
地下的先烈们纷纷打来电话询问
|
||||
大纪元
|
||||
新唐人
|
||||
淫靡
|
||||
六四事件
|
||||
迷昏药
|
||||
|
|
@ -44,8 +11,6 @@ fuck
|
|||
麻醉乙醚
|
||||
短信群发器
|
||||
帝国之梦
|
||||
毛一鲜
|
||||
黎阳平
|
||||
对日强硬
|
||||
出售枪支
|
||||
摇头丸
|
||||
|
|
@ -60,8 +25,6 @@ PK黑社会
|
|||
昏药
|
||||
侦探设备
|
||||
麻醉钢枪
|
||||
反华
|
||||
官商勾结
|
||||
升达毕业证
|
||||
戴海静
|
||||
自杀指南
|
||||
|
|
@ -72,13 +35,8 @@ PK黑社会
|
|||
强效失意药
|
||||
迷奸药
|
||||
透视眼镜
|
||||
远程偷拍
|
||||
自制手枪
|
||||
激情小电影
|
||||
黄色小电影
|
||||
天鹅之旅
|
||||
盘古乐队
|
||||
高校暴乱
|
||||
高校群体事件
|
||||
大学骚乱
|
||||
高校骚乱
|
||||
|
|
@ -98,8 +56,6 @@ PK黑社会
|
|||
反政府
|
||||
禁书
|
||||
特码
|
||||
国民党
|
||||
贪污
|
||||
骚妇
|
||||
法论功
|
||||
江湖淫娘
|
||||
|
|
@ -152,34 +108,22 @@ AV
|
|||
玉蒲团
|
||||
隐形喷剂
|
||||
反雷达测速
|
||||
假币
|
||||
代开发票
|
||||
假钞
|
||||
窃听
|
||||
电话拦截系统
|
||||
探测狗
|
||||
手机卡复制器
|
||||
手机跟踪定位器
|
||||
监听器
|
||||
针孔摄像
|
||||
监听宝
|
||||
迷幻药
|
||||
手拍肩
|
||||
迷魂香
|
||||
麻古
|
||||
政治风波
|
||||
政府软弱
|
||||
政府无能
|
||||
九评
|
||||
十七大代表
|
||||
暴力拆迁
|
||||
轮暴致死
|
||||
暴力镇压
|
||||
高干子弟名单
|
||||
性免费电影
|
||||
全裸
|
||||
偷拍
|
||||
中共十七大
|
||||
徐和柴学友
|
||||
修炼之歌
|
||||
警察殴打
|
||||
|
|
@ -187,7 +131,6 @@ AV
|
|||
李沛瑶遇害
|
||||
美国凯德
|
||||
肥东交警
|
||||
中央军委
|
||||
针对台湾
|
||||
梁保华
|
||||
MC军团
|
||||
|
|
@ -195,7 +138,6 @@ MC军团
|
|||
伪民运
|
||||
采花堂
|
||||
中国劳工通讯
|
||||
评中国共产党
|
||||
建立生活性补贴
|
||||
中共走狗
|
||||
中共小丑
|
||||
|
|
@ -236,7 +178,6 @@ A集中营
|
|||
江独裁
|
||||
李屠夫
|
||||
江恶人
|
||||
中共特务
|
||||
乙醚
|
||||
党内分裂
|
||||
圆明网
|
||||
|
|
@ -282,7 +223,6 @@ A集中营
|
|||
特务民运
|
||||
中共警察
|
||||
中共监狱
|
||||
中共政权
|
||||
中共迫害
|
||||
自由联邦
|
||||
中共独枭
|
||||
|
|
@ -307,9 +247,6 @@ H漫画
|
|||
买春堂
|
||||
苏东解体
|
||||
反右题材
|
||||
隐私图片
|
||||
卫星接收器
|
||||
卫星电视
|
||||
信号拦截器
|
||||
新闻通气会
|
||||
山西洪洞
|
||||
|
|
@ -405,10 +342,6 @@ H漫画
|
|||
艳照门
|
||||
奴役童工
|
||||
性奴
|
||||
计生风暴
|
||||
厦门大游行
|
||||
想不到的黑幕
|
||||
死亡笔记
|
||||
二奶
|
||||
2奶
|
||||
纪股票市场五卅惨案
|
||||
|
|
@ -427,51 +360,13 @@ H漫画
|
|||
毛爷爷复活
|
||||
智能H3
|
||||
智能H3
|
||||
赣江学院
|
||||
江西田园置业集团
|
||||
海乐神
|
||||
酣乐欣
|
||||
高莺莺
|
||||
完全自杀手册
|
||||
无界
|
||||
广东王
|
||||
口头检查
|
||||
三句硬话
|
||||
红海湾
|
||||
升达
|
||||
沈阳公安
|
||||
拦截器
|
||||
阻无通畅
|
||||
民为法执
|
||||
尾行
|
||||
电车之狼
|
||||
绕过封锁
|
||||
本拉登
|
||||
汕尾事件
|
||||
公务员工资
|
||||
公务员调资
|
||||
鸡吧
|
||||
公务员的工资
|
||||
反中游行
|
||||
支持台湾
|
||||
双鞋的故事
|
||||
中国军用运输机
|
||||
科技精英遇难
|
||||
湘阴杨林
|
||||
杨林寨
|
||||
湘阴县杨林
|
||||
死刑枪毙
|
||||
马加爵
|
||||
死刑过程
|
||||
学生与警察
|
||||
鬼村
|
||||
重题工
|
||||
先烈的电电
|
||||
身份证生成
|
||||
短信猫
|
||||
车牌反光
|
||||
次下跪
|
||||
求救遭拒
|
||||
邪恶的党
|
||||
出售迷药
|
||||
针孔摄像机
|
||||
|
|
@ -483,53 +378,6 @@ H漫画
|
|||
大揭露
|
||||
突破封锁
|
||||
多党执政
|
||||
生成身份证
|
||||
华国锋
|
||||
叶剑英
|
||||
李先念
|
||||
汪东兴
|
||||
韦国清
|
||||
乌兰夫
|
||||
刘伯承
|
||||
许世友
|
||||
纪登奎
|
||||
苏振华
|
||||
余秋里
|
||||
张廷发
|
||||
陈永贵
|
||||
陈锡联
|
||||
耿飚
|
||||
聂荣臻
|
||||
倪志福
|
||||
徐向前
|
||||
邓颖超
|
||||
杨尚昆
|
||||
杨得志
|
||||
宋任穷
|
||||
胡乔木
|
||||
胡耀邦
|
||||
廖承志
|
||||
秦基伟
|
||||
陈慕华
|
||||
田纪云
|
||||
李铁映
|
||||
李锡铭
|
||||
杨汝岱
|
||||
吴学谦
|
||||
胡启立
|
||||
芮杏文
|
||||
杨白冰
|
||||
邹家华
|
||||
谭绍文
|
||||
王汉斌
|
||||
任建新
|
||||
于永波
|
||||
傅全有
|
||||
王乐泉
|
||||
王兆国
|
||||
刘云山
|
||||
张立昌
|
||||
张德江
|
||||
隐形耳机
|
||||
隐形摄像头
|
||||
裸聊
|
||||
|
|
@ -589,21 +437,8 @@ a级情片
|
|||
保钓
|
||||
鲍戈
|
||||
鲍彤
|
||||
暴乱
|
||||
暴政
|
||||
北韩
|
||||
藏独
|
||||
曹长青
|
||||
曹刚川
|
||||
陈炳基
|
||||
陈破空
|
||||
陈希同
|
||||
陈小同
|
||||
陈宣良
|
||||
陈一谘
|
||||
陈总统
|
||||
程铁军
|
||||
迟浩田
|
||||
持不同政见
|
||||
赤匪
|
||||
赤化
|
||||
|
|
@ -618,16 +453,11 @@ a级情片
|
|||
地下教会
|
||||
地下刊物
|
||||
电视流氓
|
||||
钓鱼岛
|
||||
丁关根
|
||||
丁子霖
|
||||
东北独立
|
||||
东社
|
||||
东土耳其斯坦
|
||||
东西南北论坛
|
||||
动乱
|
||||
独裁
|
||||
独裁政治
|
||||
独夫
|
||||
独立台湾会
|
||||
屙民
|
||||
|
|
@ -638,16 +468,11 @@ a级情片
|
|||
法仑
|
||||
法伦
|
||||
法轮
|
||||
法论
|
||||
反封锁技术
|
||||
反腐败论坛
|
||||
反共
|
||||
李洪志
|
||||
法轮功
|
||||
江泽民
|
||||
毛泽东
|
||||
邓小平
|
||||
胡锦涛
|
||||
推翻
|
||||
打倒
|
||||
台独
|
||||
|
|
@ -672,8 +497,6 @@ a级情片
|
|||
迷药
|
||||
强迫
|
||||
色情
|
||||
三級
|
||||
三级
|
||||
A片
|
||||
喷精
|
||||
偷窥
|
||||
|
|
@ -836,7 +659,6 @@ A片
|
|||
避孕套
|
||||
你妈逼
|
||||
大鸡巴
|
||||
政治
|
||||
卖春
|
||||
买春
|
||||
朱容基
|
||||
|
|
@ -849,8 +671,6 @@ A片
|
|||
疆独
|
||||
新疆独立
|
||||
大盖帽
|
||||
黑社会
|
||||
夜总会
|
||||
妈个
|
||||
坐台
|
||||
腐败
|
||||
|
|
@ -869,13 +689,11 @@ A片
|
|||
吸储
|
||||
张五常
|
||||
张丕林
|
||||
空难
|
||||
吴邦国
|
||||
曾庆红
|
||||
黄菊
|
||||
吴官正
|
||||
贾庆林
|
||||
专制
|
||||
大紀元
|
||||
江澤民
|
||||
朱鎔基
|
||||
|
|
@ -890,44 +708,23 @@ A片
|
|||
吳邦國
|
||||
曾慶紅
|
||||
賈慶林
|
||||
反人类
|
||||
反社会
|
||||
方励之
|
||||
方舟子
|
||||
斐得勒
|
||||
费良勇
|
||||
分家在
|
||||
分裂
|
||||
粉饰太平
|
||||
风雨神州
|
||||
风雨神州论坛
|
||||
封从德
|
||||
冯东海
|
||||
冯素英
|
||||
佛展千手法
|
||||
付申奇
|
||||
傅申奇
|
||||
傅志寰
|
||||
高文谦
|
||||
高薪养廉
|
||||
高瞻
|
||||
高自联
|
||||
鸽派
|
||||
个人崇拜
|
||||
工自联
|
||||
共产
|
||||
共党
|
||||
共匪
|
||||
共狗
|
||||
共军
|
||||
关卓中
|
||||
贯通两极法
|
||||
郭伯雄
|
||||
郭罗基
|
||||
郭岩华
|
||||
国家安全
|
||||
国家机密
|
||||
国军
|
||||
国贼
|
||||
韩东方
|
||||
韩联潮
|
||||
|
|
@ -939,10 +736,6 @@ A片
|
|||
洪传
|
||||
洪哲胜
|
||||
胡紧掏
|
||||
胡锦滔
|
||||
胡锦淘
|
||||
胡景涛
|
||||
胡总书记
|
||||
护法
|
||||
花花公子
|
||||
华建敏
|
||||
|
|
@ -985,67 +778,14 @@ A片
|
|||
抗议
|
||||
邝锦文
|
||||
劳动教养所
|
||||
劳改
|
||||
劳教
|
||||
老江
|
||||
老毛
|
||||
黎安友
|
||||
李洪宽
|
||||
李继耐
|
||||
李兰菊
|
||||
李少民
|
||||
李淑娴
|
||||
李旺阳
|
||||
李文斌
|
||||
李月月鸟
|
||||
李志绥
|
||||
连胜德
|
||||
廉政大论坛
|
||||
梁光烈
|
||||
梁擎墩
|
||||
两岸关系
|
||||
两岸三地论坛
|
||||
两个中国
|
||||
廖锡龙
|
||||
林保华
|
||||
林长盛
|
||||
林樵清
|
||||
林慎立
|
||||
刘宾深
|
||||
刘宾雁
|
||||
刘国凯
|
||||
刘华清
|
||||
刘俊国
|
||||
刘凯中
|
||||
刘千石
|
||||
刘山青
|
||||
刘士贤
|
||||
刘文胜
|
||||
刘晓波
|
||||
刘晓竹
|
||||
刘永川
|
||||
龙虎豹
|
||||
陆委会
|
||||
吕京花
|
||||
吕秀莲
|
||||
抡功
|
||||
轮大
|
||||
罗礼诗
|
||||
马大维
|
||||
马良骏
|
||||
马三家
|
||||
马时敏
|
||||
卖国
|
||||
毛厕洞
|
||||
毛贼东
|
||||
美国参考
|
||||
美国之音
|
||||
蒙独
|
||||
蒙古独立
|
||||
密穴
|
||||
绵恒
|
||||
民国
|
||||
民进党
|
||||
民联
|
||||
民意
|
||||
民意论坛
|
||||
|
|
@ -1073,7 +813,6 @@ A片
|
|||
人民内情真相
|
||||
人民真实
|
||||
人民之声论坛
|
||||
人权
|
||||
善恶有报
|
||||
上海帮
|
||||
邵家健
|
||||
|
|
@ -1087,14 +826,6 @@ A片
|
|||
双十节
|
||||
水扁
|
||||
税力
|
||||
司马晋
|
||||
司马璐
|
||||
司徒华
|
||||
斯诺
|
||||
四川独立
|
||||
宋书元
|
||||
苏绍智
|
||||
苏晓康
|
||||
台盟
|
||||
台湾狗
|
||||
台湾建国运动组织
|
||||
|
|
@ -1110,36 +841,8 @@ A片
|
|||
统独
|
||||
统独论坛
|
||||
统战
|
||||
屠杀
|
||||
外交与方略
|
||||
万润南
|
||||
万晓东
|
||||
王宝森
|
||||
王炳章
|
||||
王超华
|
||||
王辅臣
|
||||
王涵万
|
||||
王沪宁
|
||||
王军涛
|
||||
王力雄
|
||||
王瑞林
|
||||
王润生
|
||||
王若望
|
||||
王希哲
|
||||
王秀丽
|
||||
王冶坪
|
||||
网特
|
||||
魏新生
|
||||
温元凯
|
||||
文革
|
||||
无界浏览器
|
||||
吴百益
|
||||
吴方城
|
||||
吴弘达
|
||||
吴宏达
|
||||
吴仁华
|
||||
吴学灿
|
||||
吴学璨
|
||||
吾尔开希
|
||||
五不
|
||||
洗脑
|
||||
|
|
@ -1207,12 +910,10 @@ A片
|
|||
正义党论坛
|
||||
换妻
|
||||
真木加美
|
||||
超爽
|
||||
毛片
|
||||
打手枪
|
||||
欲望
|
||||
脚交
|
||||
伦理
|
||||
艳星
|
||||
三陪
|
||||
绝色
|
||||
|
|
@ -1239,7 +940,6 @@ A片
|
|||
天安门一代
|
||||
自民党
|
||||
自由民主论坛
|
||||
走私
|
||||
淫穴
|
||||
幼女
|
||||
舆论
|
||||
|
|
@ -1252,7 +952,6 @@ fa轮
|
|||
指点江山论坛
|
||||
中俄边界
|
||||
中功
|
||||
中共
|
||||
中国威胁论
|
||||
中国问题论坛
|
||||
中国之春
|
||||
|
|
@ -1275,7 +974,6 @@ fa轮
|
|||
狗卵子
|
||||
我操你
|
||||
狗b
|
||||
法功
|
||||
群奸
|
||||
狗操
|
||||
猪操
|
||||
|
|
@ -1357,7 +1055,6 @@ B样
|
|||
淫图
|
||||
交媾
|
||||
护士
|
||||
自拍
|
||||
大片
|
||||
夫妻
|
||||
流血
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
6-4tianwang
|
||||
89-64cdjp
|
||||
ADMIN
|
||||
Administrator
|
||||
asshole
|
||||
BLOWJOB
|
||||
chinaliberal
|
||||
|
|
@ -12,7 +10,6 @@ creaders
|
|||
Crestbone
|
||||
dajiyuan
|
||||
dfdz
|
||||
DICK
|
||||
falun
|
||||
falundafa
|
||||
Feelmistone
|
||||
|
|
@ -22,7 +19,6 @@ fuck
|
|||
gcd
|
||||
Gruepin
|
||||
Guichuideng
|
||||
HACKING
|
||||
hongzhi
|
||||
hrichina
|
||||
HUANET
|
||||
|
|
@ -31,14 +27,9 @@ incest
|
|||
jiangdongriji
|
||||
jiaochuang
|
||||
jiaochun
|
||||
KEFU
|
||||
KISSMYASS
|
||||
lihongzhi
|
||||
minghui
|
||||
minghuinews
|
||||
nacb
|
||||
Neckromancer
|
||||
NMIS
|
||||
PAPER64
|
||||
penis
|
||||
qiangjian
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
- 6-4tianwang
|
||||
- 89-64cdjp
|
||||
- ADMIN
|
||||
- Administrator
|
||||
- asshole
|
||||
- BLOWJOB
|
||||
- chinaliberal
|
||||
|
|
@ -13,7 +11,6 @@
|
|||
- Crestbone
|
||||
- dajiyuan
|
||||
- dfdz
|
||||
- DICK
|
||||
- falun
|
||||
- falundafa
|
||||
- Feelmistone
|
||||
|
|
@ -23,7 +20,6 @@
|
|||
- gcd
|
||||
- Gruepin
|
||||
- Guichuideng
|
||||
- HACKING
|
||||
- hongzhi
|
||||
- hrichina
|
||||
- HUANET
|
||||
|
|
@ -32,14 +28,9 @@
|
|||
- jiangdongriji
|
||||
- jiaochuang
|
||||
- jiaochun
|
||||
- KEFU
|
||||
- KISSMYASS
|
||||
- lihongzhi
|
||||
- minghui
|
||||
- minghuinews
|
||||
- nacb
|
||||
- Neckromancer
|
||||
- NMIS
|
||||
- PAPER64
|
||||
- penis
|
||||
- qiangjian
|
||||
|
|
|
|||
|
|
@ -67,9 +67,15 @@ defaults format: :json do
|
|||
collection do
|
||||
post :check_user_id
|
||||
post :check_user_login
|
||||
post 'access_token', to: 'user_tokens#show'
|
||||
end
|
||||
end
|
||||
|
||||
scope 'organizations/:owner', module: :organizations do
|
||||
resources :sync_repositories, only: [:create]
|
||||
resources :projects, only: [:index]
|
||||
end
|
||||
|
||||
scope ':owner' do
|
||||
resource :users, path: '/', only: [:update, :edit, :destroy] do
|
||||
collection do
|
||||
|
|
@ -188,6 +194,7 @@ defaults format: :json do
|
|||
resources :runs, only: [:index, :create] do
|
||||
post '/jobs/:job', to: 'runs#job_show'
|
||||
post '/rerun', to: 'runs#rerun'
|
||||
post '/cancel', to: 'runs#cancel'
|
||||
post '/jobs/:job/rerun', to: 'runs#job_rerun'
|
||||
get '/jobs/:job/logs', to: 'runs#job_logs'
|
||||
end
|
||||
|
|
@ -203,6 +210,7 @@ defaults format: :json do
|
|||
resources :pulls, module: 'pulls' do
|
||||
member do
|
||||
get :files
|
||||
post :reopen
|
||||
end
|
||||
resources :versions, only: [:index] do
|
||||
member do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
class AddProjectIndexGpid < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :projects, :gpid
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
class CreateProjectActions < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :project_actions do |t|
|
||||
t.references :project
|
||||
t.string :type
|
||||
t.integer :user_id
|
||||
t.text :event_extra
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class AddUserIndexGiteaToken < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :users, :gitea_token
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class AddRemoteIpToFeedbacks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :feedbacks, :remote_ip, :string
|
||||
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
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue