Merge branch 'standalone_develop' into pre_trustie_server

This commit is contained in:
xxq250 2025-03-13 14:07:15 +08:00
commit e17021b9c1
20 changed files with 146 additions and 163 deletions

View File

@ -1,11 +1,3 @@
GIT
remote: https://gitlink.org.cn/KingChan/sonarqube.git
revision: 80f07d427322ef02c0714c77a382e87aed0bef81
specs:
sonarqube (1.3.0)
httparty (~> 0.14, >= 0.14.0)
terminal-table (~> 1.5, >= 1.5.1)
GEM
remote: https://mirrors.cloud.tencent.com/rubygems/
specs:
@ -107,6 +99,7 @@ GEM
archive-zip (~> 0.10)
nokogiri (~> 1.8)
chunky_png (1.3.11)
coderay (1.1.3)
concurrent-ruby (1.1.6)
connection_pool (2.2.2)
crass (1.0.6)
@ -143,7 +136,7 @@ GEM
fugit (1.4.1)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.4)
gitea-client (1.4.6)
gitea-client (1.5.9)
rest-client (~> 2.1.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
@ -156,11 +149,8 @@ GEM
hashie (3.6.0)
htmlentities (4.3.4)
http-accept (1.7.0)
http-cookie (1.0.5)
http-cookie (1.0.8)
domain_name (~> 0.5)
httparty (0.21.0)
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
io-like (0.3.1)
@ -189,7 +179,8 @@ GEM
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
loofah (2.4.0)
logger (1.6.6)
loofah (2.20.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@ -198,9 +189,10 @@ GEM
mimemagic (~> 0.3.2)
maruku (0.7.3)
method_source (0.9.2)
mime-types (3.5.2)
mime-types (3.6.0)
logger
mime-types-data (~> 3.2015)
mime-types-data (3.2024.0507)
mime-types-data (3.2025.0220)
mimemagic (0.3.10)
nokogiri (~> 1)
rake
@ -255,6 +247,11 @@ GEM
popper_js (1.16.0)
powerpack (0.1.2)
prettier (0.18.2)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.3)
puma (5.6.8)
nio4r (~> 2.0)
@ -448,8 +445,6 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thor (1.0.1)
thread_safe (0.3.6)
tilt (2.0.10)
@ -460,9 +455,7 @@ GEM
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.9.1)
unf (0.2.0)
unicode-display_width (1.6.1)
web-console (3.7.0)
actionview (>= 5.0)
@ -504,7 +497,7 @@ DEPENDENCIES
enumerize
faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0)
gitea-client (~> 1.4.3)
gitea-client (~> 1.5.8)
grape-entity (~> 0.7.1)
groupdate (~> 4.1.0)
harmonious_dictionary (~> 0.0.1)
@ -514,6 +507,7 @@ DEPENDENCIES
kaminari (~> 1.1, >= 1.1.1)
letter_avatar
listen (>= 3.0.5, < 3.2)
loofah (~> 2.20.0)
mysql2 (>= 0.4.4, < 0.6.0)
oauth2
omniauth (~> 1.9.0)
@ -526,6 +520,7 @@ DEPENDENCIES
parallel (~> 1.19, >= 1.19.1)
pdfkit
prettier
pry-rails
puma (~> 5.6.5)
rack-cors
rails (~> 5.2.0)
@ -552,7 +547,6 @@ DEPENDENCIES
simple_xlsx_reader (~> 1.0.4)
sinatra
solargraph (~> 0.38.0)
sonarqube!
spreadsheet
spring
spring-watcher-listen (~> 2.0.0)

View File

@ -67,9 +67,9 @@ class Action::NodeInputsController < ApplicationController
def node_input_params
if params.require(:action_node_input)
params.require(:action_node_input).permit(:name, :input_type, :description, :is_required, :sort_no)
params.require(:action_node_input).permit(:name, :input_type, :description, :is_required, :sort_no, :default_value)
else
params.permit(:name, :input_type, :description, :is_required, :sort_no)
params.permit(:name, :input_type, :description, :is_required, :sort_no, :default_value)
end
end
end

View File

@ -71,7 +71,7 @@ class Api::Pm::SprintIssuesController < Api::Pm::BaseController
begin
case complete_params[:complete_type].to_i
when 1
@issues.update_all(status_id: 5)
@issues.update_all(status_id: 5, due_date: Time.now)
when 2
@issues.update_all(pm_sprint_id: 0)
when 3

View File

@ -47,6 +47,7 @@ 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.save
render_ok({ pipeline_yaml: pipeline_yaml, pipeline_name: params[:pipeline_name], file_name: @pipeline.file_name, sha: sha.present? ? sha : file['content']['sha'] })
end
@ -79,8 +80,8 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
def destroy
@pipeline = Action::Pipeline.find(params[:id])
if pipeline
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, content_params("update"))
if @pipeline
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, del_content_params.merge(identifier: @project.identifier))
tip_exception(interactor.error) unless interactor.success?
@pipeline.destroy!
end
@ -114,7 +115,7 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
def show
@pipeline = Action::Pipeline.find_by(id: params[:id])
@pipeline = Action::Pipeline.new(id: 0, pipeline_name: "test-ss", yaml: build_test_yaml) if @pipeline.blank?
# @pipeline = Action::Pipeline.new(id: 0, pipeline_name: "test-ss", yaml: build_test_yaml) if @pipeline.blank?
end
def build_pipeline_yaml_new(pipeline_name, pipeline_json)
@ -172,6 +173,15 @@ class Api::V1::Projects::PipelinesController < Api::V1::BaseController
}
end
def del_content_params(opt)
{
filepath: ".gitea/workflows/#{@pipeline.pipeline_name}.yml",
base64_filepath: Base64.encode64(".gitea/workflows/#{@pipeline.pipeline_name}.yml").gsub(/\n/, ''),
branch: @pipeline.branch,
sha: get_pipeline_file_sha(@pipeline.file_name, @pipeline.branch)
}
end
def build_nodes(params_nodes)
steps_nodes = []
params_nodes.each do |input_node|

View File

@ -421,24 +421,6 @@ class ApplicationController < ActionController::Base
"#{edu_setting('git_address_domain')}/#{repo_path}"
end
# 通关后,把最后一次成功的代码存到数据库
# type 0 创始内容, 1 最新内容
# def game_passed_code(path, myshixun, game_id)
# # 如果代码窗口是隐藏的,则不用保存代码
# return if myshixun.shixun.hide_code || myshixun.shixun.vnc
# file_content = git_fle_content myshixun.repo_path, path
# #unless file_content.present?
# # raise("获取文件代码异常")
# #end
# logger.info("#######game_id:#{game_id}, file_content:#{file_content}")
# game_code = GameCode.where(:game_id => game_id, :path => path).first
# if game_code.nil?
# GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path)
# else
# game_code.update_attributes!(:new_code => file_content)
# end
# end
# Post请求
def uri_post(uri, params)
begin
@ -530,112 +512,6 @@ class ApplicationController < ActionController::Base
end
# 实训主类别列表,自带描述
def shixun_main_type
list = []
mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_main_mirror
mirrors.try(:each) do |mirror|
list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description), mirror_name: mirror.name}
end
list
end
# 小类别列表
def shixun_small_type
list = []
mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_small_mirror
mirrors.try(:each) do |mirror|
list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description, mirror_name: mirror.name}
end
list
end
def container_limit(mirror_repositories)
container = []
mirror_repositories.each do |mr|
if mr.name.present?
container << {:image => mr.name, :cpuLimit => mr.cpu_limit, :memoryLimit => "#{mr.memory_limit}M", :type => mr.try(:main_type) == "1" ? "main" : "sub"}
end
end
container.to_json
end
# 实训中间层pod配置
def shixun_container_limit shixun
container = []
shixun.shixun_service_configs.each do |config|
mirror = config.mirror_repository
if mirror.name.present?
# 资源限制没有就传默认值。
cpu_limit = config.cpu_limit.presence || 1
cpu_request = config.lower_cpu_limit.presence || 0.1
memory_limit = config.memory_limit.presence || 1024
request_limit = config.request_limit.presence || 10
resource_limit = config.resource_limit.presence || 10000
container << {:image => mirror.name,
:cpuLimit => cpu_limit,
:cpuRequest => cpu_request,
:memoryLimit => "#{memory_limit}M",
:memoryRequest => "#{request_limit}M",
:resourceLimit => "#{resource_limit}K",
:type => mirror.try(:main_type) == "1" ? "main" : "sub"}
end
end
container.to_json
end
# 毕设任务列表的赛选
def course_work(task, **option)
logger.info("#############{option}")
course = task.course
work_list = task.graduation_works.includes(user: [:user_extension])
# 教师评阅搜索 0: 未评, 1 已评
if option[:teacher_comment]
graduation_work_ids = GraduationWorkScore.where(graduation_work_id: work_list.map(&:id)).pluck(:graduation_work_id)
if option[:teacher_comment].zero?
work_list = work_list.where.not(id: graduation_work_ids)
elsif option[:teacher_comment] == 1
work_list = work_list.where(id: graduation_work_ids).where.not(work_status: 0)
end
end
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交
if option[:task_status]
work_list = work_list.where(work_status: option[:task_status])
end
# 分班情况
if option[:course_group]
group_user_ids = course.course_members.where(course_group_id: option[:course_group]).pluck(:user_id)
# 有分组只可能是老师身份查看列表
work_list = work_list.where(user_id: group_user_ids)
end
# 只看我的交叉评阅
if option[:cross_comment]
graduation_work_id = task.graduation_work_comment_assignations.where(:user_id => current_user.id)
.pluck(:graduation_work_id).uniq if task.graduation_work_comment_assignations
work_list = work_list.where(id: graduation_work_id)
end
# 输入姓名和学号搜索
# TODO user_extension 如果修改 请调整
if option[:search]
work_list = work_list.joins(user: :user_extension).where("concat(lastname, firstname) like ?
or student_id like ?", "%#{option[:search]}%", "%#{option[:search]}%")
end
# 排序
rorder = UserExtension.column_names.include?(option[:order]) ? option[:order] : "updated_at"
b_order = %w(desc asc).include?(option[:b_order]) ? option[:b_order] : "desc"
if rorder == "created_at" || rorder == "work_score"
work_list = work_list.order("graduation_works.#{rorder} #{b_order}")
elsif rorder == "student_id"
work_list = work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end
work_list
end
def strip_html(text, len=0, endss="...")
ss = ""
if !text.nil? && text.length>0
@ -1176,15 +1052,46 @@ class ApplicationController < ActionController::Base
# 接口限流,请求量大有性能问题
def request_limit
record_count = Rails.cache.read("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H%M')}/#{request.remote_ip}")
white_list_ip = ["106.75.110.152"]
unless white_list_ip.include?(request.remote_ip)
record_count = Rails.cache.read("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H')}/#{request.remote_ip}")
if record_count.present?
record_count = record_count + 1
else
record_count = 1
end
Rails.logger.info("请求太快,请稍后再试。#{controller_name}::#{request.remote_ip}") if record_count > 200
tip_exception("请求太快,请稍后再试。") if record_count > 200
Rails.cache.write("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H')}/#{request.remote_ip}", record_count, expires_in: 1.hour)
end
end
def check_batch_requests
check_key = "request.remote_ip:#{request.remote_ip}"
result = Rails.cache.read(check_key)
if result.present?
if result.to_i > 100
tip_exception(401, '暂时无法请求,请稍后再试')
else
Rails.cache.write(check_key, result.to_i + 1)
end
else
Rails.cache.write(check_key, 1, expires_in: 1.hour)
end
end
def request_raw_limit
record_count = Rails.cache.read("request/#{request.path}/#{Time.now.strftime('%Y%m%d%H')}}")
if record_count.present?
record_count = record_count + 1
else
record_count = 1
end
tip_exception("请求太快,请稍后再试。") if record_count > 100
Rails.logger.info("请求太快,请稍后再试。#{request.path}") if record_count > 1000
tip_exception("请求太快,请稍后再试。") if record_count > 1000
Rails.cache.write("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H%M')}/#{request.remote_ip}", record_count, expires_in: 1.minute)
Rails.cache.write("request/#{request.path}/#{Time.now.strftime('%Y%m%d%H')}}", record_count, expires_in: 1.hour)
end
end

View File

@ -4,4 +4,8 @@ class LicensesController < ApplicationController
q = License.ransack(name_cont: params[:name])
@licenses = q.result(distinct: true)
end
def show
@license = License.find(params[:id])
end
end

View File

@ -14,6 +14,8 @@ class RepositoriesController < ApplicationController
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
before_action :get_statistics, only: %i[top_counts]
before_action :require_referer, only: [:raw]
# before_action :request_limit, only: [:raw]
before_action :request_raw_limit, only: [:raw]
def files
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
@ -298,7 +300,7 @@ class RepositoriesController < ApplicationController
redirect_to file_path
end
def raw
def raw
domain = GiteaService.gitea_config[:domain]
api_url = GiteaService.gitea_config[:base_url]

View File

@ -263,7 +263,7 @@ class UsersController < ApplicationController
begin
@user = current_user
begin
result = Notice::Read::CountService.call(current_user.id)
result = EduSetting.get("notice_disable").to_s == "true" ? nil : Notice::Read::CountService.call(current_user.id)
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
rescue
@message_unread_total = 0

View File

@ -33,7 +33,7 @@ class Action::Pipeline < ApplicationRecord
belongs_to :user, optional: true
belongs_to :project
validates :name, presence: { message: "不能为空" }
validates :pipeline_name, presence: { message: "不能为空" }
validates :json, length: { maximum: 65535, too_long: "不能超过65535个字符"}
validates :yaml, length: { maximum: 65535, too_long: "不能超过65535个字符"}
end

View File

@ -88,6 +88,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
@updated_issue.project_id = @project_id unless @project_id.nil?
@updated_issue.updated_on = Time.now
@updated_issue.changer_id = @current_user.id
@updated_issue.due_date = Time.now if @due_date.blank?
@updated_issue.save!
build_after_issue_journal_details if @updated_issue.previous_changes.present? # 操作记录

View File

@ -23,6 +23,10 @@
<%= form.label :description, "描述" %>
<%= form.text_area :description, rows: 5, :style => 'width:800px;' %>
</div>
<div class="field">
<%= form.label :default_value, "默认值" %>
<%= form.text_field :default_value %>
</div>
<div class="field">
<%= form.label :is_required, "是否必填项" %>
<%= form.check_box("is_required", {}, "true", "false") %>

View File

@ -1,4 +1,4 @@
json.extract! node_input, :id, :name, :input_type, :description
json.extract! node_input, :id, :name, :input_type, :description, :is_required, :default_value
if node_input.input_type.to_s == "select"
json.select node.action_node_selects do |node_select|
json.partial! "node_select", locals: { node_select: node_select, node: node }

View File

@ -27,6 +27,10 @@
<%= form.label :description, "描述" %>
<%= form.text_area :description, rows: 5, :style => 'width:800px;' %>
</div>
<div class="field">
<%= form.label :default_value, "默认值" %>
<%= form.text_field :default_value %>
</div>
<div class="field">
<%= form.label :is_required, "是否必填项" %>
<%= form.check_box("is_required", {}, "true", "false") %>

View File

@ -1,4 +1,4 @@
json.extract! node_input, :id, :name, :input_type, :description, :is_required
json.extract! node_input, :id, :name, :input_type, :description, :is_required, :default_value
if node_input.input_type.to_s == "select"
json.select node.action_node_selects do |node_select|
json.partial! "node_select", locals: { node_select: node_select, node: node }

View File

@ -30,7 +30,7 @@
<li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores', has_permission: current_user.admin?) %></li>
<% end %>
</li>
<!-- <li><%#= sidebar_item(admins_laboratories_path, '导航栏配置', icon: 'cloud', controller: 'admins-laboratories', has_permission: current_user.admin?) %></li>-->
<li><%= sidebar_item(admins_laboratories_path, '导航栏配置', icon: 'cloud', controller: 'admins-laboratories', has_permission: current_user.admin?)%></li>
<li>
<%= sidebar_item_group('#setting-system', '开发者配置', icon: 'wrench', has_permission: current_user.admin?) do %>
<li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites', has_permission: current_user.admin?) %></li>

View File

@ -0,0 +1,3 @@
json.id @license.id
json.name @license.name
json.content @license.content

View File

@ -10,6 +10,7 @@ json.projects @projects do |project|
json.praises_count project.praises_count.to_i
json.forked_count project.forked_count.to_i
json.is_public project.is_public
json.license_id project.license_id
json.mirror_url project.repository&.mirror_url
json.type project&.numerical_for_project_type
json.last_update_time render_unix_time(project.updated_on)
@ -50,7 +51,7 @@ json.projects @projects do |project|
json.name project.project_language.name
end
end
json.topics project.project_topics.each do |topic|
json.topics project.project_topics.each do |topic|
json.(topic, :id, :name)
end
end

View File

@ -66,6 +66,7 @@ else
json.private !@project.is_public
end
json.license_name @project.license_name
json.license_id @project.license_id
json.branches_count @result[:branch_tag_total_count].present? ? (@result[:branch_tag_total_count]['branch_count'] || 0) : 0
json.tags_count @result[:branch_tag_total_count].present? ? (@result[:branch_tag_total_count]['tag_count'] || 0) : 0
# json.contributors do

47
config/puma.rb.example Normal file
View File

@ -0,0 +1,47 @@
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 8 }
threads threads_count, threads_count * 2
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 4000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 8 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
# preload_app!
before_fork do
require 'puma_worker_killer'
PumaWorkerKiller.config do |config|
config.ram = 2048 # mb
config.frequency = 20 # seconds
config.percent_usage = 0.98
#config.rolling_restart_frequency = 12 * 3600 # 12 hours in seconds, or 12.hours if using Rails
end
PumaWorkerKiller.start
end
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

View File

@ -0,0 +1,5 @@
class AddActionNodeInputDefaultValue < ActiveRecord::Migration[5.2]
def change
add_column :action_node_inputs, :default_value, :string
end
end