forked from Gitlink/forgeplus
Merge branch 'standalone_develop' into dev_osredm_server
# Conflicts: # app/controllers/accounts_controller.rb # app/controllers/admins/users_controller.rb # app/controllers/application_controller.rb # app/controllers/owners_controller.rb # app/helpers/application_helper.rb # app/helpers/avatar_helper.rb # app/models/edu_setting.rb # app/models/user.rb # app/models/user_action.rb # app/views/layouts/admin.html.erb # app/views/projects/index.json.jbuilder # config/harmonious_dictionary/chinese_dictionary.txt # config/harmonious_dictionary/harmonious.hash # config/harmonious_dictionary/harmonious_english.yml # config/routes/api.rb
This commit is contained in:
commit
b760d17988
3
Gemfile
3
Gemfile
|
@ -1,5 +1,6 @@
|
|||
#source 'https://gems.ruby-china.com'
|
||||
source 'https://mirrors.cloud.tencent.com/rubygems/'
|
||||
#source 'https://rubygems.org'
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
gem 'rails', '~> 5.2.0'
|
||||
|
@ -141,6 +142,6 @@ gem 'doorkeeper'
|
|||
|
||||
gem 'doorkeeper-jwt'
|
||||
|
||||
gem 'gitea-client', '~> 1.5.8'
|
||||
gem 'gitea-client', '~> 1.6.1'
|
||||
|
||||
gem 'loofah', '~> 2.20.0'
|
40
Gemfile.lock
40
Gemfile.lock
|
@ -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)
|
||||
|
|
|
@ -6,7 +6,7 @@ class Action::NodeInputsController < ApplicationController
|
|||
@node_inputs = @node.action_node_inputs
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json
|
||||
format.json{ render_ok(data: @node_inputs.as_json) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -4,6 +4,10 @@ class Action::NodeTypesController < ApplicationController
|
|||
|
||||
def index
|
||||
@node_types = Action::NodeType.all
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render_ok(data: @node_types.as_json) }
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -20,7 +24,10 @@ class Action::NodeTypesController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render_ok(data: @node_type.as_json) }
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
|
@ -45,7 +52,10 @@ class Action::NodeTypesController < ApplicationController
|
|||
else
|
||||
flash[:danger] = '删除失败'
|
||||
end
|
||||
redirect_to action_node_types_path
|
||||
respond_to do |format|
|
||||
format.html { redirect_to action_node_types_path }
|
||||
format.json { render_ok }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
class Action::NodesController < ApplicationController
|
||||
before_action :require_admin, except: [:index]
|
||||
# before_action :require_admin, except: [:index]
|
||||
before_action :require_login
|
||||
before_action :find_action_node, except: [:index, :create, :new]
|
||||
|
||||
def index
|
||||
@node_types = Action::NodeType.all
|
||||
no_node_type = Action::NodeType.find_by(name: "未分类")
|
||||
@no_type_nodes = Action::Node.where(action_node_types_id: nil)
|
||||
@no_type_nodes = Action::Node.where(action_node_types_id: nil).or(Action::Node.where(action_node_types_id: no_node_type.id)) if no_node_type.present?
|
||||
respond_to do |format|
|
||||
format.html { @nodes = Action::Node.all }
|
||||
format.html { @nodes = Action::Node.where("name LIKE :search OR full_name LIKE :search", :search => "%#{params[:search]}%") }
|
||||
format.json
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@node = Action::Node.new(node_params)
|
||||
if params.require(:node).present? && params.require(:node)[:link_type_array].present?
|
||||
@node.link_type = (params.require(:node)[:link_type_array] - [""]).join(",")
|
||||
end
|
||||
@node.user_id = current_user.id
|
||||
respond_to do |format|
|
||||
if @node.save
|
||||
format.html { redirect_to action_nodes_path, notice: '创建成功.' }
|
||||
|
@ -33,10 +40,16 @@ class Action::NodesController < ApplicationController
|
|||
end
|
||||
|
||||
def edit
|
||||
|
||||
if @node.link_type.present?
|
||||
@node.link_type_array = @node.link_type.to_s.split(",")
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if params.require(:node).present? && params.require(:node)[:link_type_array].present?
|
||||
@node.link_type = (params.require(:node)[:link_type_array] - [""]).join(",")
|
||||
end
|
||||
@node.user_id = current_user.id if @node.user_id.blank?
|
||||
@node.update(node_params)
|
||||
respond_to do |format|
|
||||
format.html { redirect_to action_nodes_path, notice: '更新成功.' }
|
||||
|
@ -50,7 +63,10 @@ class Action::NodesController < ApplicationController
|
|||
else
|
||||
flash[:danger] = '删除失败'
|
||||
end
|
||||
redirect_to action_nodes_path
|
||||
respond_to do |format|
|
||||
format.html { redirect_to action_nodes_path }
|
||||
format.json { render_ok() }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -61,9 +77,11 @@ class Action::NodesController < ApplicationController
|
|||
|
||||
def node_params
|
||||
if params.require(:action_node)
|
||||
params.require(:action_node).permit(:name, :label, :full_name, :description, :icon, :action_node_types_id, :is_local, :local_url, :yaml, :sort_no)
|
||||
params.require(:action_node).permit(:name, :label, :full_name, :description, :icon, :action_node_types_id,
|
||||
:is_local, :local_url, :yaml, :sort_no, :node_type, :is_mutil_link, :link_type, :link_type_array)
|
||||
else
|
||||
params.permit(:name, :label, :full_name, :description, :icon, :action_node_types_id, :is_local, :local_url, :yaml, :sort_no)
|
||||
params.permit(:name, :label, :full_name, :description, :icon, :action_node_types_id, :is_local, :local_url,
|
||||
:yaml, :sort_no, :node_type, :is_mutil_link, :link_type, :link_type_array)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,7 +49,10 @@ class Action::TemplatesController < ApplicationController
|
|||
else
|
||||
flash[:danger] = '删除失败'
|
||||
end
|
||||
redirect_to action_templates_path
|
||||
respond_to do |format|
|
||||
format.html { redirect_to action_templates_path }
|
||||
format.json { render_ok }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -2,7 +2,7 @@ class Admins::NpsController < Admins::BaseController
|
|||
before_action :require_business
|
||||
def index
|
||||
@on_off_switch = EduSetting.get("nps-on-off-switch").to_s == 'true'
|
||||
@user_nps = UserNp.joins(:user).order(created_at: :desc)
|
||||
@user_nps = UserNp.order(created_at: :desc)
|
||||
keyword = params[:keyword].to_s.strip.presence
|
||||
if keyword
|
||||
sql = 'CONCAT(users.lastname, users.firstname) LIKE :keyword OR users.nickname LIKE :keyword OR users.login LIKE :keyword OR users.mail LIKE :keyword OR users.phone LIKE :keyword'
|
||||
|
|
|
@ -6,7 +6,7 @@ class Admins::ProjectsController < Admins::BaseController
|
|||
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
search = params[:search].to_s.strip
|
||||
projects = Project.where("name like ? OR identifier LIKE ?", "%#{search}%", "%#{search}%").order("#{sort_by} #{sort_direction}")
|
||||
projects = Project.where("id = ? OR name like ? OR identifier LIKE ?", search, "%#{search}%", "%#{search}%").order("#{sort_by} #{sort_direction}")
|
||||
case params[:category]
|
||||
when 'public'
|
||||
projects = projects.where(is_public: true)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
class Admins::UserActionsController < Admins::BaseController
|
||||
before_action :require_admin
|
||||
|
||||
def index
|
||||
@user_actions = UserAction.order(created_at: :desc)
|
||||
@user_actions = @user_actions.where(action_type: params[:action_type]) if params[:action_type].present?
|
||||
keyword = params[:keyword].to_s.strip.presence
|
||||
if keyword
|
||||
sql = 'login LIKE :keyword OR phone LIKE :keyword OR email LIKE :keyword'
|
||||
@user_actions = @user_actions.where(sql, keyword: "%#{keyword}%")
|
||||
end
|
||||
@user_actions = paginate @user_actions
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
class Admins::UsersController < Admins::BaseController
|
||||
before_action :require_admin
|
||||
before_action :finder_user, except: [:index, :export]
|
||||
before_action :finder_user, except: [:index, :export]
|
||||
|
||||
def index
|
||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||
|
@ -37,9 +37,12 @@ class Admins::UsersController < Admins::BaseController
|
|||
|
||||
def destroy
|
||||
UserAction.create(action_id: @user.id, action_type: "DestroyUser", user_id: current_user.id, :ip => request.remote_ip, data_bank: @user.attributes.to_json)
|
||||
@user.destroy!
|
||||
Gitea::User::DeleteService.call(@user.login)
|
||||
|
||||
@result_object = Api::V1::Users::DeleteUserService.call(@user)
|
||||
if @result_object
|
||||
render_delete_success
|
||||
else
|
||||
render_js_error('删除失败!')
|
||||
end
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
class Api::Pm::ActionRunsController < Api::Pm::BaseController
|
||||
before_action :require_login
|
||||
|
||||
def index
|
||||
tip_exception('请输入workflows') if params[:workflows].blank?
|
||||
@owner = Owner.find_by(login: params[:owner_id].to_s) || Owner.find_by(id: params[:owner_id].to_s)
|
||||
tip_exception('组织未找到') if @owner.blank?
|
||||
action_runs = Gitea::ActionRun.where(owner_id: @owner.gitea_uid)
|
||||
group_data = action_runs.where(workflow_id: params[:workflows].to_s.split(",")).where(status: [1,2]).group(:workflow_id, :status).count
|
||||
@result = []
|
||||
params[:workflows].to_s.split(",").each do |file|
|
||||
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,
|
||||
schedule: last_action_run.schedule_id > 0,
|
||||
title: last_action_run.title,
|
||||
index: last_action_run.index,
|
||||
status: last_action_run.status,
|
||||
started: last_action_run.started,
|
||||
stopped: last_action_run.stopped,
|
||||
length: last_action_run.stopped - last_action_run.started,
|
||||
created: last_action_run.created,
|
||||
updated: last_action_run.updated,
|
||||
} : {}
|
||||
|
||||
total = 0
|
||||
success = 0
|
||||
failure = 0
|
||||
group_data.each do |k,v|
|
||||
total += v if k[0] == file
|
||||
success += v if k[0] == file && k[1] == 1
|
||||
failure += v if k[0] == file && k[1] == 2
|
||||
end
|
||||
|
||||
@result << {
|
||||
name: file,
|
||||
total: total,
|
||||
success: success,
|
||||
failure: failure
|
||||
}.merge(last_action_run_json)
|
||||
end
|
||||
render :json => {data: @result}
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,138 @@
|
|||
class Api::Pm::DashboardsController < Api::Pm::BaseController
|
||||
before_action :require_login
|
||||
def index
|
||||
end
|
||||
|
||||
def todo
|
||||
return render_error('请输入正确的pm_project_ids.') if params[:pm_project_ids].blank?
|
||||
pm_project_ids = params[:pm_project_ids].split(",") rescue []
|
||||
date = params[:date].present? ? params[:date].to_date : Date.today rescue Date.today
|
||||
@issues = Issue.where("start_date <= ? and due_date >= ?", date, date)
|
||||
@issues = @issues.where(pm_project_id: pm_project_ids).joins(:issue_participants).where(issue_participants: {participant_id: current_user.id, participant_type: 'assigned'})
|
||||
@issues = @issues.where.not(status_id: 5)
|
||||
@issues = kaminari_paginate(@issues.distinct.pm_includes)
|
||||
end
|
||||
|
||||
def my_issues
|
||||
return render_error('请输入正确的pm_project_ids.') if params[:pm_project_ids].blank?
|
||||
return render_error('请输入正确的pm_issue_types.') if params[:pm_issue_types].blank?
|
||||
pm_project_ids = params[:pm_project_ids].split(",") rescue []
|
||||
pm_issue_types = params[:pm_issue_types].split(",") rescue []
|
||||
@all_issues = Issue.where(pm_project_id: pm_project_ids, pm_issue_type: pm_issue_types)
|
||||
@issues = @all_issues.joins(:issue_participants).where(issue_participants: {participant_id: current_user.id})
|
||||
@issues = @issues.where.not(status_id: 5) if params[:category] == "opened"
|
||||
|
||||
@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
|
||||
@my_assign_bugs_count = @all_issues.where(pm_issue_type: 3).joins(:issue_participants).where(issue_participants: {participant_id: current_user.id, participant_type: 'assigned'}).size
|
||||
end
|
||||
|
||||
def my_pm_projects
|
||||
return render_error('请输入正确的pm_project_id.') if params[:pm_project_id].blank?
|
||||
@all_issues = Issue.where(pm_project_id: params[:pm_project_id])
|
||||
time_now = Time.now
|
||||
@last_week_create_issues_count = @all_issues.where("created_on > ? and created_on < ?", time_now - 7.days, time_now).size
|
||||
@before_last_week_create_issue_count = @all_issues.where("created_on > ? and created_on < ?", time_now - 14.days, time_now - 7.days).size
|
||||
@compare_last_week_create_issues = @before_last_week_create_issue_count.zero? ? 0 :(@last_week_create_issues_count - @before_last_week_create_issue_count).to_f / @before_last_week_create_issue_count rescue 0
|
||||
@last_week_close_issues_count = @all_issues.where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 7.days, time_now).size
|
||||
@before_last_week_close_issue_count = @all_issues.where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 14.days, time_now - 7.days).size
|
||||
@compare_last_week_close_issues = @before_last_week_close_issue_count.zero? ? 0 :(@last_week_close_issues_count - @before_last_week_close_issue_count).to_f / @before_last_week_close_issue_count rescue 0
|
||||
@all_requirement_issues_count = @all_issues.where(pm_issue_type: 1).size
|
||||
@open_requirement_issues_count = @all_issues.where(pm_issue_type: 1).where.not(status_id: 5).size
|
||||
@last_week_close_requirement_issues_count = @all_issues.where(pm_issue_type: 1).where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 7.days, time_now).size
|
||||
@last_month_close_requirement_issues_count = @all_issues.where(pm_issue_type: 1).where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 30.days, time_now).size
|
||||
@all_task_issues_count = @all_issues.where(pm_issue_type: 2).size
|
||||
@open_task_issues_count = @all_issues.where(pm_issue_type: 2).where.not(status_id: 5).size
|
||||
@last_week_close_tast_issues_count = @all_issues.where(pm_issue_type: 2).where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 7.days, time_now).size
|
||||
@last_month_close_task_issues_count = @all_issues.where(pm_issue_type: 2).where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 30.days, time_now).size
|
||||
@all_bug_issues_count = @all_issues.where(pm_issue_type: 3).size
|
||||
@open_bug_issues_count = @all_issues.where(pm_issue_type: 3).where.not(status_id: 5).size
|
||||
@last_week_close_bug_issues_count = @all_issues.where(pm_issue_type: 3).where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 7.days, time_now).size
|
||||
@last_month_close_bug_issues_count = @all_issues.where(pm_issue_type: 3).where(status_id: 5).where("updated_on > ? and updated_on < ?", time_now - 30.days, time_now).size
|
||||
|
||||
|
||||
@requirement_close_trend = [[],[]]
|
||||
@task_close_trend = [[],[]]
|
||||
@bug_close_trend = [[],[]]
|
||||
((time_now-29.days).to_date..time_now.to_date).to_a.each do |i|
|
||||
@requirement_close_trend[0] << i.strftime("%Y.%m.%d")
|
||||
@task_close_trend[0] << i.strftime("%Y.%m.%d")
|
||||
@bug_close_trend[0] << i.strftime("%Y.%m.%d")
|
||||
@requirement_close_trend[1] << @all_issues.where(pm_issue_type: 1, status_id: 5).where("DATE(updated_on) = ?", i).size
|
||||
@task_close_trend[1] << @all_issues.where(pm_issue_type: 2, status_id: 5).where("DATE(updated_on) = ?", i).size
|
||||
@bug_close_trend[1] << @all_issues.where(pm_issue_type: 3, status_id: 5).where("DATE(updated_on) = ?", i).size
|
||||
end
|
||||
@close_trend = {requirement: @requirement_close_trend, task: @task_close_trend, bug: @bug_close_trend}
|
||||
|
||||
render_ok(data: {
|
||||
last_week_close_issues_count: @last_week_close_issues_count,
|
||||
before_last_week_close_issue_count: @before_last_week_close_issue_count,
|
||||
compare_last_week_close_issues: @compare_last_week_close_issues,
|
||||
last_week_create_issues_count: @last_week_create_issues_count,
|
||||
before_last_week_create_issue_count: @before_last_week_create_issue_count,
|
||||
compare_last_week_create_issues: @compare_last_week_create_issues,
|
||||
all_requirement_issues_count: @all_requirement_issues_count,
|
||||
open_requirement_issues_count: @open_requirement_issues_count,
|
||||
last_week_close_requirement_issues_count: @last_week_close_requirement_issues_count,
|
||||
last_month_close_requirement_issues_count: @last_month_close_requirement_issues_count,
|
||||
all_task_issues_count: @all_task_issues_count,
|
||||
open_task_issues_count: @open_task_issues_count,
|
||||
last_week_close_task_issues_count: @last_week_close_tast_issues_count,
|
||||
last_month_close_task_issues_count: @last_month_close_task_issues_count,
|
||||
all_bug_issues_count: @all_bug_issues_count,
|
||||
open_bug_issues_count: @open_bug_issues_count,
|
||||
last_week_close_bug_issues_count: @last_week_close_bug_issues_count,
|
||||
last_month_close_bug_issues_count: @last_month_close_bug_issues_count,
|
||||
close_trend: @close_trend
|
||||
})
|
||||
end
|
||||
|
||||
def my_projects
|
||||
return render_error('请输入正确的project_id.') if params[:project_id].blank?
|
||||
|
||||
@project = Project.find_by_id params[:project_id]
|
||||
return render_error('请输入正确的project_id.') unless @project.present?
|
||||
time_now = Time.now
|
||||
|
||||
branch_tag_result = $gitea_hat_client.get_repos_branch_tag_count_by_owner_repo(@project&.owner&.login, @project&.identifier) rescue {}
|
||||
languages_result = $gitea_client.get_repos_languages_by_owner_repo(@project&.owner&.login, @project&.identifier) rescue {}
|
||||
|
||||
@open_pull_requests_count = @project.pull_requests.opening.size
|
||||
@last_week_close_pull_requests_count = @project.pull_requests.where(status: 1).where("updated_at > ? and updated_at < ?", time_now - 7.days, time_now).size
|
||||
@last_month_close_pull_requets_count = @project.pull_requests.where(status: 1).where("updated_at > ? and updated_at < ?", time_now - 30.days, time_now).size
|
||||
|
||||
@commits_count = @project.commit_logs.size
|
||||
@last_week_commits_count = @project.commit_logs.where("created_at > ? and created_at < ?", time_now - 7.days, time_now).size
|
||||
@last_month_commits_count = @project.commit_logs.where("created_at > ? and created_at < ?", time_now - 30.days, time_now).size
|
||||
|
||||
render_ok(data: {
|
||||
branch_count: branch_tag_result["branch_count"].to_i,
|
||||
tag_count: branch_tag_result["tag_count"].to_i,
|
||||
license_name: @project.license&.name,
|
||||
open_pull_requests_count: @open_pull_requests_count,
|
||||
last_week_close_pull_requests_count: @last_week_close_pull_requests_count,
|
||||
last_month_close_pull_requets_count: @last_month_close_pull_requets_count,
|
||||
commits_count: @commits_count,
|
||||
last_week_commits_count: @last_week_commits_count,
|
||||
last_month_commits_count: @last_month_commits_count,
|
||||
language: hash_transform_precentagable(languages_result),
|
||||
})
|
||||
end
|
||||
|
||||
def my_operate_journals
|
||||
return render_error('请输入正确的pm_project_id.') if params[:pm_project_id].blank?
|
||||
@journals = Journal.operate_journals.joins(:issue).where(issues: {pm_project_id: params[:pm_project_id], pm_issue_type: [1,2,3]})
|
||||
|
||||
@journals = kaminari_paginate(@journals.order(updated_on: :desc))
|
||||
end
|
||||
|
||||
private
|
||||
def hash_transform_precentagable(hash)
|
||||
total_byte_size = hash.values.sum
|
||||
hash.transform_values { |v|
|
||||
ActionController::Base.helpers
|
||||
.number_to_percentage((v * 100.0 / total_byte_size), precision: 1)
|
||||
}.select{|k,v| v != "0.0%"}
|
||||
end
|
||||
end
|
|
@ -237,7 +237,47 @@ class Api::Pm::IssuesController < Api::Pm::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
def link_issues
|
||||
children_issues = @issue.pm_issue_type == 1 ? @issue.child_count > 0 ? Issue.where(id: @issue.id) : Issue.none : Issue.where(root_id: @issue.id)
|
||||
linkable_issues = Issue.where(id: PmLink.where(linkable_type: "Issue", linkable_id: @issue.id).pluck(:be_linkable_id))
|
||||
belinkable_issues = Issue.where(id: PmLink.where(be_linkable_type: "Issue", be_linkable_id: @issue.id).pluck(:linkable_id))
|
||||
|
||||
full_link_issues_ids = children_issues.pluck(:id) | linkable_issues.pluck(:id) | belinkable_issues.pluck(:id)
|
||||
compare_link_issues_ids = children_issues.pluck(:id) | linkable_issues.pluck(:id) | belinkable_issues.pluck(:id)
|
||||
i = compare_link_issues_ids.count
|
||||
while i > 0 do
|
||||
children_issues = Issue.where(root_id: compare_link_issues_ids)
|
||||
linkable_issues = Issue.where(id: PmLink.where(linkable_type: "Issue", linkable_id: compare_link_issues_ids).pluck(:be_linkable_id))
|
||||
belinkable_issues = Issue.where(id: PmLink.where(be_linkable_type: "Issue", be_linkable_id: compare_link_issues_ids).pluck(:linkable_id))
|
||||
|
||||
compare_link_issues_ids = (children_issues.pluck(:id) | linkable_issues.pluck(:id) | belinkable_issues.pluck(:id)) - full_link_issues_ids
|
||||
full_link_issues_ids = full_link_issues_ids | compare_link_issues_ids
|
||||
i = compare_link_issues_ids.count
|
||||
end
|
||||
exclude_issues_ids = []
|
||||
exclude_issues = Issue.where(id: full_link_issues_ids).where.not(root_id: nil)
|
||||
exclude_issues.each do |i|
|
||||
exclude_issues_ids << i.id if i.pm_issue_type == 1 && full_link_issues_ids.include?(i.root_id)
|
||||
end
|
||||
full_link_issues_ids = full_link_issues_ids - exclude_issues_ids
|
||||
@requirement_issues = Issue.where(id:full_link_issues_ids, pm_issue_type:1, root_id: nil).pm_includes
|
||||
@task_issues = Issue.where(id:full_link_issues_ids, pm_issue_type:2).pm_includes
|
||||
@bug_issues = Issue.where(id:full_link_issues_ids, pm_issue_type:3).pm_includes
|
||||
end
|
||||
|
||||
private
|
||||
def circle_link_issues(issue_ids)
|
||||
if issue_ids.present?
|
||||
children_issues = Issue.joins(:parent_issue).where(issues: {id: issue_ids})
|
||||
linkable_issues = Issue.where(id: PmLink.where(linkable_type: "Issue", linkable_id: issue_ids))
|
||||
belinkable_issues = Issue.where(id: PmLink.where(be_linkable_type: "Issue", be_linkable_id: issue_ids))
|
||||
|
||||
return circle_link_issues(children_issues.pluck(:id))
|
||||
else
|
||||
return []
|
||||
end
|
||||
end
|
||||
|
||||
def check_issue_operate_permission
|
||||
return if params[:project_id].to_i.zero?
|
||||
render_forbidden('您没有操作权限!') unless @project.member?(current_user) || current_user.admin? || @issue.user == current_user
|
||||
|
|
|
@ -56,12 +56,15 @@ class Api::Pm::ProjectsController < Api::Pm::BaseController
|
|||
def statistics
|
||||
return tip_exception '参数错误' if params[:pm_project_id].blank?
|
||||
@issues = Issue.where(pm_project_id: params[:pm_project_id], pm_issue_type:[1, 2, 3])
|
||||
@last_week_close_issues = @issues.where(status_id: 5).where("updated_on > ? and updated_on < ?", Time.now - 7.days, Time.now)
|
||||
last_week_close_type_count_data = @last_week_close_issues.group(:pm_issue_type).count
|
||||
type_count_data = @issues.group(:pm_issue_type).count
|
||||
type_status = @issues.group(:pm_issue_type,:status_id).count
|
||||
type_status_data = {}
|
||||
IssueStatus.all.map do |e|
|
||||
# next if e.id == 5
|
||||
[1,2,3].map{ |type|
|
||||
next if type == 1 && [1, 6].include?(e.id)
|
||||
type_status_data[type] = {} if type_status_data[type].nil?
|
||||
if type_status[[type,e.id]].nil?
|
||||
type_status_data[type][e.id] = 0
|
||||
|
@ -71,9 +74,9 @@ class Api::Pm::ProjectsController < Api::Pm::BaseController
|
|||
}
|
||||
end
|
||||
open_data = {
|
||||
"1": type_status_data[1][1].to_i + type_status_data[1][2].to_i,
|
||||
"2": type_status_data[2][1].to_i + type_status_data[2][2].to_i,
|
||||
"3": type_status_data[3][1].to_i + type_status_data[3][2].to_i,
|
||||
"1": type_status_data[1][1].to_i + type_status_data[1][2].to_i + type_status_data[1][3].to_i + type_status_data[1][6].to_i,
|
||||
"2": type_status_data[2][1].to_i + type_status_data[2][2].to_i + type_status_data[2][3].to_i + type_status_data[2][6].to_i,
|
||||
"3": type_status_data[3][1].to_i + type_status_data[3][2].to_i + type_status_data[3][3].to_i + type_status_data[3][6].to_i,
|
||||
}
|
||||
if type_count_data.keys.size < 3
|
||||
nedd_add = [1,2,3] - type_count_data.keys
|
||||
|
@ -81,17 +84,24 @@ class Api::Pm::ProjectsController < Api::Pm::BaseController
|
|||
type_count_data[e] = 0
|
||||
}
|
||||
end
|
||||
if last_week_close_type_count_data.keys.size < 3
|
||||
nedd_add = [1,2,3] - last_week_close_type_count_data.keys
|
||||
nedd_add.map{ |e|
|
||||
last_week_close_type_count_data[e] = 0
|
||||
}
|
||||
end
|
||||
data = {
|
||||
pie_chart: type_count_data,
|
||||
bar_chart: type_status_data,
|
||||
open_data: open_data
|
||||
open_data: open_data,
|
||||
last_week_close_data: last_week_close_type_count_data,
|
||||
}
|
||||
render_ok(data: data)
|
||||
end
|
||||
|
||||
def polyline
|
||||
return tip_exception '参数错误' if params[:pm_project_id].blank?
|
||||
time_line = (Time.current.beginning_of_day - 6.day) .. Time.current
|
||||
time_line = (Time.current.beginning_of_day - 29.day) .. Time.current
|
||||
@create_issues = Issue.where(pm_project_id: params[:pm_project_id],created_on: time_line)
|
||||
@due_issues = Issue.where(pm_project_id: params[:pm_project_id],status_id:[3,5],due_date: time_line)
|
||||
@create_issues_count = @create_issues.group(:pm_issue_type,"DATE(created_on)").count
|
||||
|
@ -100,7 +110,7 @@ class Api::Pm::ProjectsController < Api::Pm::BaseController
|
|||
create_issues: {},
|
||||
due_issues: {}
|
||||
}
|
||||
7.times do |time|
|
||||
30.times do |time|
|
||||
current_time = Date.current - time.day
|
||||
if @create_issues_count.present?
|
||||
data[:create_issues][current_time] = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -46,7 +46,7 @@ class Api::V1::Issues::JournalsController < Api::V1::BaseController
|
|||
end
|
||||
|
||||
def load_issue
|
||||
@issue = @project.issues.issue_issue.where(project_issues_index: params[:index]).where.not(id: params[:index]).take || Issue.find_by_id(params[:index])
|
||||
@issue = @project.issues.issue_issue.where(project_issues_index: params[:index]).where.not(id: params[:index]).take || @project.issues.issue_issue.find_by_id(params[:index])
|
||||
if @issue.blank?
|
||||
render_not_found("疑修不存在!")
|
||||
end
|
||||
|
|
|
@ -70,7 +70,7 @@ class Api::V1::IssuesController < Api::V1::BaseController
|
|||
private
|
||||
|
||||
def load_issue
|
||||
@issue = @project.issues.issue_issue.where(project_issues_index: params[:index]).where.not(id: params[:index]).take || Issue.find_by_id(params[:index])
|
||||
@issue = @project.issues.issue_issue.where(project_issues_index: params[:index]).where.not(id: params[:index]).take || @project.issues.issue_issue.find_by_id(params[:index])
|
||||
if @issue.blank?
|
||||
render_not_found("疑修不存在!")
|
||||
end
|
||||
|
|
|
@ -1,5 +1,67 @@
|
|||
class Api::V1::Projects::Actions::ActionsController < Api::V1::Projects::Actions::BaseController
|
||||
|
||||
def new_index
|
||||
@files = $gitea_client.get_repos_contents_by_owner_repo_filepath(@project&.owner&.login, @project&.identifier, ".gitea/workflows") rescue []
|
||||
@workflows = params[:workflows].split(",") if params[:workflows].present?
|
||||
@action_runs = Gitea::ActionRun.where(repo_id: @project.gpid)
|
||||
disabled_config = Gitea::RepoUnit.where(repo_id: @project.gpid, type: 10)&.first&.config
|
||||
disabled_workflows = disabled_config.present? ? JSON.parse(disabled_config)["DisabledWorkflows"] : []
|
||||
@action_runs = @action_runs.where(id: params[:ids].split(",")) if params[:ids].present?
|
||||
@action_runs = @action_runs.where(workflow_id: @workflows) if params[:workflows].present?
|
||||
group_data = @action_runs.where(status: [1,2]).group(:workflow_id, :status).count
|
||||
@result = []
|
||||
@files.map{|i|i['name']}.each do |file|
|
||||
if @workflows.present?
|
||||
next if !@workflows.include?(file)
|
||||
end
|
||||
last_action_run = @action_runs.where(workflow_id: file).order(updated: :desc).first
|
||||
last_action_run_json = last_action_run.present? ? {
|
||||
pipeline_id: Action::Pipeline.find_by(pipeline_name: file, project_id: @project.id),
|
||||
id: last_action_run.id,
|
||||
schedule: last_action_run.schedule_id > 0,
|
||||
title: last_action_run.title,
|
||||
index: last_action_run.index,
|
||||
status: last_action_run.status,
|
||||
started: last_action_run.started,
|
||||
stopped: last_action_run.stopped,
|
||||
length: last_action_run.stopped-last_action_run.started,
|
||||
created: last_action_run.created,
|
||||
updated: last_action_run.updated,
|
||||
} : {}
|
||||
|
||||
total = 0
|
||||
success = 0
|
||||
failure = 0
|
||||
group_data.each do |k,v|
|
||||
total += v if k[0] == file
|
||||
success += v if k[0] == file && k[1] == 1
|
||||
failure += v if k[0] == file && k[1] == 2
|
||||
end
|
||||
|
||||
pipeline_type = 1
|
||||
begin
|
||||
content = Gitea::Repository::Entries::GetService.call(@project&.owner, @project&.identifier, URI.escape(file), ref: last_action_run.present? ? last_action_run.ref.gsub("refs/heads/","") : @project.default_branch)['content']
|
||||
yaml_string = Base64.decode64(content).force_encoding("GBK").encode("UTF-8") unless Base64.decode64(content).force_encoding('UTF-8').valid_encoding?
|
||||
yaml_string = Base64.decode64(content).force_encoding('UTF-8')
|
||||
yml = YAML.safe_load(yaml_string)
|
||||
pipeline_type = yml.name == file.to_s.gsub(".yml","").gsub(".yaml","") ? 2 : 1
|
||||
rescue
|
||||
Rails.logger.info("#{file}不能识别流水线类型")
|
||||
end
|
||||
@result << {
|
||||
filename: file,
|
||||
disabled: disabled_workflows.include?(file.to_s),
|
||||
name: file.to_s.gsub(".yml","").gsub(".yaml","") ,
|
||||
branch: last_action_run.present? ? last_action_run.ref.gsub("refs/heads/","") : @project.default_branch,
|
||||
pipeline_type: pipeline_type,
|
||||
total: total,
|
||||
success: success,
|
||||
failure: failure
|
||||
}.merge(last_action_run_json)
|
||||
end
|
||||
render :json => {data: @result}
|
||||
end
|
||||
|
||||
def index
|
||||
begin
|
||||
gitea_result = $gitea_hat_client.get_repos_actions_by_owner_repo(@project&.owner&.login, @project&.identifier)
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
class Api::V1::Projects::Actions::RunsController < Api::V1::Projects::Actions::BaseController
|
||||
|
||||
def index
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Actions::Runs::ListService.call(@project, {workflow: params[:workflow], page: page, limit: limit}, current_user&.gitea_token)
|
||||
puts @result_object
|
||||
@begin_num = (page.to_i - 1) * limit.to_i
|
||||
# puts @result_object
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Api::V1::Projects::CommitsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:index, :diff, :recent]
|
||||
before_action :require_public_and_member_above, only: [:index, :diff, :recent, :files]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
|
||||
|
@ -10,6 +10,14 @@ class Api::V1::Projects::CommitsController < Api::V1::BaseController
|
|||
@result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def files
|
||||
if params[:filepath].present?
|
||||
@result_object = $gitea_hat_client.get_repos_commits_files_by_owner_repo_sha_filepath(@project&.owner.login, @project&.identifier, params[:sha], CGI.escape(params[:filepath]), {query: {token: current_user&.gitea_token}})
|
||||
else
|
||||
@result_object = $gitea_hat_client.get_repos_commits_files_by_owner_repo_sha(@project&.owner.login, @project&.identifier, params[:sha], {query: {token: current_user&.gitea_token, page: page, limit: limit}})
|
||||
end
|
||||
end
|
||||
|
||||
def recent
|
||||
hash = Api::V1::Projects::Commits::RecentService.call(@project, {keyword: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
|
||||
@result_object = hash[:result]
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
class Api::V1::Projects::CompareController < Api::V1::BaseController
|
||||
|
||||
before_action :require_public_and_member_above, only: [:files]
|
||||
|
||||
def files
|
||||
load_compare_params
|
||||
if params[:type] == "sha"
|
||||
@compare_result ||= gitea_compare_files(@base, @head)
|
||||
else
|
||||
@compare_result ||= @head.include?(":") ? gitea_compare_files(@base, @head) : gitea_compare_files(@head, @base)
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_compare_params
|
||||
@base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base])
|
||||
@head = params[:head].include?(":") ? Addressable::URI.unescape(params[:head].split(":")[0]) + ':' + Base64.decode64(params[:head].split(":")[1]) : Base64.decode64(params[:head])
|
||||
end
|
||||
|
||||
def gitea_compare_files(base, head)
|
||||
if params[:filepath].present?
|
||||
$gitea_hat_client.get_repos_compare_by_owner_repo_baseref_headref(@project&.owner&.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), {query: {token: current_user&.gitea_token, isFiles: true, filepath: params[:filepath]}})
|
||||
else
|
||||
$gitea_hat_client.get_repos_compare_by_owner_repo_baseref_headref(@project&.owner&.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), {query: {page:page,limit:limit,token: current_user&.gitea_token, isFiles: true}})
|
||||
end
|
||||
end
|
||||
|
||||
def get_merge_message
|
||||
if @base.blank? || @head.blank?
|
||||
return -2, "请选择分支"
|
||||
else
|
||||
return -2, "目标仓库未开启合并请求(PR)功能" unless @project.has_menu_permission("pulls")
|
||||
if @head.include?(":")
|
||||
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
||||
return -2, "请选择正确的仓库" unless fork_project.present?
|
||||
@exist_pullrequest = @project.pull_requests.where(is_original: true, head: @head.to_s.split(":")[1], base: @base, status: 0, fork_project_id: fork_project.id).take
|
||||
else
|
||||
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take
|
||||
end
|
||||
if @exist_pullrequest.present?
|
||||
return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>"
|
||||
else
|
||||
Rails.logger.info @compare_result
|
||||
if params[:filepath].present?
|
||||
if @compare_result["Commits"].blank? && @compare_result["Diff"].blank?
|
||||
return -2, "分支内容相同,无需创建合并请求"
|
||||
end
|
||||
else
|
||||
if @compare_result[:total_data].to_i < 1
|
||||
return -2, "分支内容相同,无需创建合并请求"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0, "可以合并"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
class Api::V1::Projects::OssHealthMeasuringController < Api::V1::BaseController
|
||||
|
||||
def index
|
||||
|
||||
url = URI("#{EduSetting.get("ohm_server_url")}/api/OSS_Health_Measuring/#{params[:owner]}/#{params[:repo]}")
|
||||
|
||||
http = Net::HTTP.new(url.host, url.port);
|
||||
request = Net::HTTP::Get.new(url)
|
||||
response = http.request(request)
|
||||
render :json=> response.read_body
|
||||
end
|
||||
|
||||
def keyid
|
||||
url = URI("#{EduSetting.get("ohm_server_url")}/api/OSS_Health_Measuring/#{params[:owner]}/#{params[:repo]}/#{params[:key_id]}")
|
||||
|
||||
http = Net::HTTP.new(url.host, url.port);
|
||||
request = Net::HTTP::Get.new(url)
|
||||
response = http.request(request)
|
||||
render :json=> response.read_body
|
||||
end
|
||||
|
||||
def can_get
|
||||
url = URI("#{EduSetting.get("ohm_server_url")}/api/OHM_can_get/#{params[:owner]}/#{params[:repo]}")
|
||||
|
||||
http = Net::HTTP.new(url.host, url.port);
|
||||
request = Net::HTTP::Get.new(url)
|
||||
response = http.request(request)
|
||||
render :json=> response.read_body
|
||||
end
|
||||
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
@ -6,13 +6,21 @@ class Api::V1::Projects::Pulls::PullsController < Api::V1::BaseController
|
|||
@pulls = kaminari_paginate(@pulls)
|
||||
end
|
||||
|
||||
before_action :load_pull_request, only: [:show]
|
||||
before_action :load_pull_request, only: [:show, :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 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}})
|
||||
else
|
||||
@result_object = $gitea_hat_client.get_repos_pulls_files_by_owner_repo_index(@project&.owner.login, @project&.identifier, @pull_request.gitea_number, {query: {isNew: "true",token: current_user&.gitea_token, page: page, limit: limit}})
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def query_params
|
||||
params.permit(:status, :keyword, :priority_id, :issue_tag_id, :version_id, :reviewer_id, :sort_by, :sort_direction)
|
||||
|
|
|
@ -8,6 +8,6 @@ class Api::V1::Users::ProjectsController < Api::V1::BaseController
|
|||
|
||||
private
|
||||
def query_params
|
||||
params.permit(:category, :is_public, :project_type, :sort_by, :sort_direction, :search)
|
||||
params.permit(:category, :is_public, :project_type, :sort_by, :sort_direction, :search, :start_at, :end_at)
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
class Api::V1::UsersController < Api::V1::BaseController
|
||||
include AesCryptHelper
|
||||
|
||||
before_action :load_observe_user, except: [:check_user_id, :check_user_login]
|
||||
before_action :check_auth_for_observe_user, except: [:check_user_id, :check_user_login]
|
||||
|
@ -53,7 +54,7 @@ class Api::V1::UsersController < Api::V1::BaseController
|
|||
end
|
||||
|
||||
def check_password
|
||||
password = params[:password]
|
||||
password = decrypt(params[:password]) rescue ""
|
||||
return tip_exception(-5, "8~16位密码,支持字母数字和符号") unless password =~ CustomRegexp::PASSWORD
|
||||
return tip_exception(-5, "密码错误") unless @observe_user.check_password?(password)
|
||||
render_ok
|
||||
|
@ -115,4 +116,29 @@ class Api::V1::UsersController < Api::V1::BaseController
|
|||
return render_error('更改手机号失败!')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def check_user_can_delete
|
||||
org_ids = TeamUser.where(user_id: @observe_user.id).pluck(:organization_id) | OrganizationUser.where(user_id: @observe_user.id).pluck(:organization_id)
|
||||
org_count = TeamUser.where(organization_id: org_ids).where(user_id: @observe_user.id).joins(:team).where(teams: {authorize: %w(owner)}).count
|
||||
project_count = Project.where(user_id: @observe_user.id).count
|
||||
render_ok({ can_delete: org_count == 0 && project_count == 0, org_count: org_count, project_count: project_count })
|
||||
end
|
||||
|
||||
|
||||
def destroy
|
||||
password = decrypt(params[:password]) rescue ""
|
||||
return tip_exception(-1, "密码不正确.") unless @observe_user.check_password?(password)
|
||||
org_ids = TeamUser.where(user_id: @observe_user.id).pluck(:organization_id) | OrganizationUser.where(user_id: @observe_user.id).pluck(:organization_id)
|
||||
org_count = TeamUser.where(organization_id: org_ids).where(user_id: @observe_user.id).joins(:team).where(teams: {authorize: %w(owner)}).count
|
||||
project_count = Project.where(user_id: @observe_user.id).count
|
||||
return tip_exception(-1, "当前账号名下存在拥有的组织/代码库,请先删除或转让后再尝试注销操作.") if org_count > 0 || project_count > 0
|
||||
UserAction.create(action_id: @observe_user.id, action_type: "DestroyUser", user_id: @observe_user.id, :ip => request.remote_ip, data_bank: @observe_user.attributes.to_json, memo: params[:memo])
|
||||
@result_object = Api::V1::Users::DeleteUserService.call(@observe_user)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('删除失败!')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -176,7 +176,18 @@ class ApplicationController < ActionController::Base
|
|||
# 未授权的捕捉407,弹试用申请弹框
|
||||
def require_login
|
||||
#6.13 -hs
|
||||
tip_exception(401, "请登录后再操作") unless User.current.logged?
|
||||
end
|
||||
|
||||
def require_referer
|
||||
tip_exception(403, "你没有权限访问") if request.host.present? && !request.referer.to_s.include?(request.host.to_s.gsub("www.",""))
|
||||
end
|
||||
|
||||
def require_login_or_token
|
||||
if params[:token].present?
|
||||
user = User.try_to_autologin(params[:token])
|
||||
User.current = user
|
||||
end
|
||||
tip_exception(401, "请登录后再操作") unless User.current.logged?
|
||||
end
|
||||
|
||||
|
@ -336,7 +347,7 @@ class ApplicationController < ActionController::Base
|
|||
# 多浏览器退出账号时,token不存在处理
|
||||
if current_domain_session && autologin_user.nil?
|
||||
autologin_user = (User.active.find(current_domain_session) rescue nil)
|
||||
set_autologin_cookie(autologin_user)
|
||||
set_autologin_cookie(autologin_user) if autologin_user.present?
|
||||
end
|
||||
autologin_user
|
||||
end
|
||||
|
@ -384,24 +395,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
|
||||
|
@ -493,112 +486,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
|
||||
|
@ -1143,15 +1030,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
|
||||
|
|
|
@ -30,25 +30,33 @@ class AttachmentsController < ApplicationController
|
|||
|
||||
|
||||
def get_file
|
||||
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?
|
||||
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/")
|
||||
tmp_path = "#{Rails.root}#{EduSetting.get("attachment_folder")}gitea/#{Time.now.strftime('%Y%m%d')}-#{md5_file}"
|
||||
if url.starts_with?(base_url) && !url.starts_with?("#{base_url}/repo")
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
url = ("/repos"+url.split(base_url + "/api")[1])
|
||||
filepath, ref = url.split("/")[-1].split("?")
|
||||
url.gsub!(url.split("/")[-1], '')
|
||||
Rails.logger.info("url===#{url}")
|
||||
# Rails.logger.info("url===#{url}")
|
||||
Rails.logger.info(filepath)
|
||||
request_url = [domain, api_url, URI.encode(url), URI.escape(filepath), "?ref=#{URI.escape(ref.split('ref=')[1])}&access_token=#{User.where(admin: true).take&.gitea_token}"].join
|
||||
ref = ref.blank? ? "" : URI.escape(ref.split('ref=')[1])
|
||||
request_url = [domain, api_url, URI.encode(url), URI.escape(filepath), "?ref=#{ref}&access_token=#{User.where(admin: true).take&.gitea_token}"].join
|
||||
Rails.logger.info("request_url===#{request_url}")
|
||||
response = Faraday.get(request_url)
|
||||
File.delete(tmp_path) if File.exist?(tmp_path) # 删除之前的文件
|
||||
Util.download_file(request_url, tmp_path)
|
||||
filename = filepath
|
||||
else
|
||||
response = Faraday.get(URI.encode(url))
|
||||
File.delete(tmp_path) if File.exist?(tmp_path) # 删除之前的文件
|
||||
Util.download_file(URI.encode(url), tmp_path)
|
||||
filename = params[:download_url].to_s.split("/").pop()
|
||||
end
|
||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||
send_file(tmp_path, filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -25,6 +25,16 @@ class CommitLogsController < ApplicationController
|
|||
commit_log.project_trends.create(user_id: user.id, project_id: project&.id, action_type: "create") if user.id !=2
|
||||
# 统计数据新增
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {commits: 1}, project.id)
|
||||
|
||||
commit_user = User.find_by(mail: commit[:committer][:email]) rescue nil
|
||||
commit_user = User.find_by(login: commit[:committer][:name]) if commit_user.blank? rescue nil
|
||||
next if commit_user.blank?
|
||||
|
||||
# 触发变更issue状态的job
|
||||
close_issue_content = message.to_s.scan(/\b(Close|Closes|Closed|Closing|close|closes|closed|closing)\s*(#\d+(,\s*#\d+)*)?\b/)
|
||||
ChangeIssueStatusByMessageJob.perform_later(commit_id, project, commit_user, close_issue_content[0][1], 5) if close_issue_content[0].present? && close_issue_content[0][1].present?
|
||||
solve_issue_content = message.to_s.scan(/\b(Fix|Fixes|Fixed|Fixing|fix|fixes|fixed|fixing|Resolve|Resolves|Resolved|Resolving|resolve|resolves|resolved|resolving|Implement|Implements|Implemented|Implementing|implement|implements|implemented|implementing)\s*(#\d+(,\s*#\d+)*)?\b/)
|
||||
ChangeIssueStatusByMessageJob.perform_later(commit_id, project, commit_user, solve_issue_content[0][1], 3) if solve_issue_content[0].present? && solve_issue_content[0][1].present?
|
||||
end
|
||||
# c
|
||||
if project.present?
|
||||
|
|
|
@ -18,6 +18,7 @@ class CompareController < ApplicationController
|
|||
@page_limit = page_limit <=0 ? 15 : page_limit
|
||||
@page_offset = (@page_size -1) * @page_limit
|
||||
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
|
||||
Rails.logger.info @compare_result
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -36,7 +37,7 @@ class CompareController < ApplicationController
|
|||
if @exist_pullrequest.present?
|
||||
return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>"
|
||||
else
|
||||
if @compare_result["Commits"].blank? && @compare_result["Diff"].blank?
|
||||
if @compare_result["FilesCount"].to_i == 0 && @compare_result["CommitsCount"].to_i == 0
|
||||
return -2, "分支内容相同,无需创建合并请求"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ module Api::PullHelper
|
|||
|
||||
def load_pull_request
|
||||
pull_request_id = params[:pull_id] || params[:id]
|
||||
@pull_request = @project.pull_requests.where(gitea_number: pull_request_id).where.not(id: pull_request_id).take || PullRequest.find_by_id(pull_request_id)
|
||||
@pull_request = @project.pull_requests.where(gitea_number: pull_request_id).where.not(id: pull_request_id).take || @project.pull_requests.find_by_id(pull_request_id)
|
||||
@issue = @pull_request&.issue
|
||||
if @pull_request
|
||||
logger.info "###########pull_request founded"
|
||||
|
|
|
@ -77,4 +77,12 @@ module GitHelper
|
|||
cha_path = path.present? ? path.split(";") : []
|
||||
cha_path.reject(&:blank?)[0].try(:strip)
|
||||
end
|
||||
|
||||
def expain_issue_commit(commit_message)
|
||||
respace_arr= commit_message.to_s.scan(/#(\d+)/).map{|s|[s[0], "##{s[0]}"]}.uniq.sort_by{|s|-s[0].to_i}
|
||||
respace_arr.each do |item|
|
||||
issue = Issue.find_by_id(item[0].to_i)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -75,6 +75,17 @@ module LoginHelper
|
|||
session[:"#{default_yun_session}"] = nil
|
||||
end
|
||||
|
||||
def clear_user_cookie
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookies.delete(autologin_cookie_name, domain: edu_setting('cookie_domain'))
|
||||
else
|
||||
cookies.delete(autologin_cookie_name)
|
||||
end
|
||||
# 清除前端写入的用户名
|
||||
Rails.logger.info("########________cookies['login']___________###########{cookies['login']}")
|
||||
cookies.delete("login")
|
||||
end
|
||||
|
||||
# Sets the logged in user
|
||||
def logged_user=(user)
|
||||
reset_session
|
||||
|
|
|
@ -50,7 +50,7 @@ class MarkFilesController < ApplicationController
|
|||
end
|
||||
|
||||
def load_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || @project.pull_requests.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,53 @@
|
|||
class Oauth::Ci4sController < Oauth::BaseController
|
||||
include RegisterHelper
|
||||
|
||||
|
||||
def oauth_url
|
||||
redirect_to Ci4s::Service.oauth_url
|
||||
end
|
||||
|
||||
# 需要educoder那边设置回调地址
|
||||
def create
|
||||
begin
|
||||
code = params['code'].to_s.strip
|
||||
tip_exception("code不能为空") if code.blank?
|
||||
|
||||
new_user = false
|
||||
token = Ci4s::Service.access_token(code)
|
||||
Rails.logger.info("[OAuth2] result -> #{token}")
|
||||
result = Ci4s::Service.user_info(token[:access_token])
|
||||
tip_exception("请求用户信息错误") if result['code'].to_i != 200
|
||||
user_info = result['data']
|
||||
# 存在该用户
|
||||
open_user = OpenUsers::Ci4s.find_by(uid: user_info['username'])
|
||||
if open_user.present? && open_user.user.present?
|
||||
successful_authentication(open_user.user)
|
||||
redirect_to root_path(new_user: false)
|
||||
return
|
||||
else
|
||||
if current_user.blank? || !current_user.logged?
|
||||
new_user = true
|
||||
session[:unionid] = user_info['username']
|
||||
# login = User.generate_login('E')
|
||||
login = user_info['username']
|
||||
email = user_info['email']
|
||||
email = "#{login}@forge.com" if email.blank?
|
||||
reg_result = autologin_register(login, email, "Ec#{login}2021#", 'educoder', user_info['mobile'])
|
||||
Rails.logger.info("[OAuth2] reg_result -> #{reg_result}")
|
||||
if reg_result[:message].blank?
|
||||
open_user = OpenUsers::Ci4s.create!(user_id: reg_result[:user][:id], uid: login, extra: user_info)
|
||||
successful_authentication(open_user.user)
|
||||
else
|
||||
tip_exception(reg_result[:message])
|
||||
end
|
||||
else
|
||||
OpenUsers::Ci4s.create!(user: current_user, uid: user_info['username'], extra: user_info)
|
||||
end
|
||||
end
|
||||
Rails.logger.info("[OAuth2] session[:unionid] -> #{session[:unionid]}")
|
||||
redirect_to root_path(new_user: new_user)
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
class Organizations::OrganizationsController < Organizations::BaseController
|
||||
include AesCryptHelper
|
||||
before_action :require_login, except: [:index, :show, :recommend, :languages]
|
||||
# before_action :require_profile_completed, only: [:create]
|
||||
before_action :convert_image!, only: [:create, :update]
|
||||
|
@ -139,7 +140,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
end
|
||||
|
||||
def password
|
||||
params.fetch(:password, "")
|
||||
decrypt(params[:password]) rescue ""
|
||||
end
|
||||
|
||||
def load_organization
|
||||
|
|
|
@ -10,9 +10,11 @@ class OwnersController < ApplicationController
|
|||
.distinct
|
||||
end
|
||||
|
||||
def show
|
||||
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
|
||||
# return render_not_found unless @owner.present?
|
||||
def show
|
||||
login = params[:id].to_s
|
||||
@owner = Owner.find_by(login: login) || Owner.find_by(id: login)
|
||||
clear_user_cookie unless @owner.present?
|
||||
return render_not_found unless @owner.present?
|
||||
# 组织
|
||||
if @owner.is_a?(Organization)
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
|
|
|
@ -247,6 +247,7 @@ class ProjectsController < ApplicationController
|
|||
def destroy
|
||||
if current_user.admin? || @project.manager?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
UserAction.create(action_id: @project.id, action_type: "DestroyProject", user_id: current_user.id, :ip => request.remote_ip, data_bank: @project.attributes.to_json)
|
||||
close_fork_pull_requests_by(@project)
|
||||
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier,current_user.gitea_token).call
|
||||
@project.destroy!
|
||||
|
@ -280,13 +281,19 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def watch_users
|
||||
start_at = params[:start_at]
|
||||
end_at = params[:end_at]
|
||||
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
|
||||
watchers = watchers.where("watchers.created_at > ? and watchers.created_at < ?", Time.at(start_at.to_i), Time.at(end_at.to_i)) if start_at.present? && end_at.present?
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def praise_users
|
||||
start_at = params[:start_at]
|
||||
end_at = params[:end_at]
|
||||
praises = @project.praise_treads.includes(:user).order("praise_treads.created_at desc").distinct
|
||||
praises = praises.where("praise_treads.created_at > ? and praise_treads.created_at < ?", Time.at(start_at.to_i), Time.at(end_at.to_i)) if start_at.present? && end_at.present?
|
||||
@praises_count = praises.size
|
||||
@praises = paginate(praises)
|
||||
end
|
||||
|
@ -365,7 +372,7 @@ class ProjectsController < ApplicationController
|
|||
if @project_detail.save!
|
||||
attachment_ids = Array(params[:attachment_ids])
|
||||
logger.info "=============> #{Array(params[:attachment_ids])}"
|
||||
@attachments = Attachment.where(id: attachment_ids)
|
||||
@attachments = Attachment.where(id: attachment_ids).or(Attachment.where(uuid: attachment_ids))
|
||||
@attachments.update_all(
|
||||
container_id: @project_detail.id,
|
||||
container_type: @project_detail.model_name.name,
|
||||
|
|
|
@ -302,11 +302,11 @@ class PullRequestsController < ApplicationController
|
|||
|
||||
private
|
||||
def load_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || @project.pull_requests.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def find_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || @project.pull_requests.find_by_id(params[:id])
|
||||
@issue = @pull_request&.issue
|
||||
if @pull_request.blank?
|
||||
normal_status(-1, "合并请求不存在")
|
||||
|
|
|
@ -13,6 +13,9 @@ class RepositoriesController < ApplicationController
|
|||
before_action :get_ref, only: %i[entries sub_entries top_counts files archive]
|
||||
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)
|
||||
|
@ -151,8 +154,8 @@ class RepositoriesController < ApplicationController
|
|||
return render_error('暂未开放,敬请期待.')
|
||||
else
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token, {diff: true})
|
||||
render_error(@commit[:message], @commit[:status]) if @commit.has_key?(:status) || @commit_diff.has_key?(:status)
|
||||
# @commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token, {diff: true})
|
||||
render_error(@commit[:message], @commit[:status]) if @commit.has_key?(:status)#|| @commit_diff.has_key?(:status)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -298,7 +301,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]
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class ReviewsController < ApplicationController
|
|||
end
|
||||
|
||||
def load_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || @project.pull_requests.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
end
|
|
@ -54,9 +54,9 @@ class SitePagesController < ApplicationController
|
|||
user = User.find_by_login params[:repository][:owner][:login]
|
||||
return normal_status(-1, '你还未开通Page服务,无法进行部署') unless user.website_permission
|
||||
|
||||
project = Project.where(identifier: params[:repository][:name],user_id: user.id)
|
||||
return normal_status(-1, '你没有权限操作') if project.owner?(user)
|
||||
return normal_status(-1, '该仓库还未开通Page服务,无法进行部署') if Page.exists?(user: user, project: project)
|
||||
project = Project.find_by(identifier: params[:repository][:name],user_id: user.id)
|
||||
return normal_status(-1, '项目不存在') if project.nil?
|
||||
return normal_status(-1, '该仓库还未开通Page服务,无法进行部署') unless Page.exists?(user: user, project: project)
|
||||
|
||||
@page = Page.find_by(user: user, project: project)
|
||||
response_str = @page.deploy_page(branch)
|
||||
|
|
|
@ -257,7 +257,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
|
||||
|
@ -712,6 +712,7 @@ class UsersController < ApplicationController
|
|||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
clear_user_cookie unless @user.present?
|
||||
end
|
||||
|
||||
def user_params
|
||||
|
|
|
@ -5,7 +5,10 @@ class WatchersController < ApplicationController
|
|||
before_action :get_target
|
||||
|
||||
def index
|
||||
start_at = params[:start_at]
|
||||
end_at = params[:end_at]
|
||||
scope = @target.watchers.includes(:user)
|
||||
scope = scope.where("watchers.created_at > ? and watchers.created_at < ?", Time.at(start_at.to_i), Time.at(end_at.to_i)) if start_at.present? && end_at.present?
|
||||
@watchers = paginate(scope)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class BaseForm
|
||||
include ActiveModel::Model
|
||||
include AesCryptHelper
|
||||
|
||||
Error = Class.new(StandardError)
|
||||
EmailError = Class.new(Error)
|
||||
|
@ -53,11 +54,15 @@ class BaseForm
|
|||
end
|
||||
|
||||
def check_password(password)
|
||||
password = decrypt(password) rescue ""
|
||||
password = strip(password)
|
||||
raise PasswordFormatError, "密码8~20位密码,支持字母数字和符号" unless password =~ CustomRegexp::PASSWORD
|
||||
end
|
||||
|
||||
def check_password_confirmation(password, password_confirmation)
|
||||
password = decrypt(password) rescue ""
|
||||
password_confirmation = decrypt(password_confirmation) rescue ""
|
||||
|
||||
password = strip(password)
|
||||
password_confirmation = strip(password_confirmation)
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
module AesCryptHelper
|
||||
|
||||
AES_KEY = EduSetting.get("login_crypt_key") || '59c96c3572ab8cc1'
|
||||
|
||||
def encrypt(plain_text, output_encoding = 'base64')
|
||||
|
||||
# 将字符串密钥和IV转换为16字节的字节数组
|
||||
key = AES_KEY.byteslice(0, 16)
|
||||
iv = AES_KEY.byteslice(0, 16)
|
||||
|
||||
# 创建并设置AES-CBC加密器
|
||||
cipher = OpenSSL::Cipher.new('AES-128-CBC')
|
||||
cipher.encrypt
|
||||
cipher.key = key
|
||||
cipher.iv = iv
|
||||
|
||||
# 加密数据,并添加PKCS7填充
|
||||
encrypted_data = cipher.update(plain_text) + cipher.final
|
||||
# 将加密数据转换为Base64编码
|
||||
Base64.strict_encode64(encrypted_data)
|
||||
end
|
||||
|
||||
def decrypt(cipher_text, input_encoding = 'base64')
|
||||
# 确保密钥是16字节长
|
||||
key = AES_KEY.byteslice(0, 16) # 如果密钥不足16字节,填充空格;如果超过,截断
|
||||
iv = AES_KEY.byteslice(0, 16)
|
||||
|
||||
decipher = OpenSSL::Cipher.new('AES-128-CBC')
|
||||
decipher.decrypt
|
||||
decipher.key = key
|
||||
decipher.iv = iv
|
||||
|
||||
# 根据输入编码解码密文
|
||||
decrypted_data = case input_encoding
|
||||
when 'base64'
|
||||
Base64.strict_decode64(cipher_text)
|
||||
else
|
||||
cipher_text
|
||||
end
|
||||
|
||||
decrypted = decipher.update(decrypted_data) + decipher.final
|
||||
decrypted
|
||||
end
|
||||
|
||||
end
|
|
@ -146,11 +146,11 @@ module ApplicationHelper
|
|||
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
||||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
ctime = File.ctime(disk_filename(source&.class, source&.id)).to_i
|
||||
if %w(User Organization).include?(source&.class.to_s)
|
||||
File.join("images", relative_path, ["#{source&.class}", "#{source&.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
File.join("images/avatars", ["#{source&.class}", "#{source&.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
# source.get_letter_avatar_url
|
||||
|
|
|
@ -13,11 +13,11 @@ module AvatarHelper
|
|||
|
||||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
ctime = File.ctime(disk_filename(source&.class, source&.id)).to_i
|
||||
if %w(User Organization).include?(source&.class.to_s)
|
||||
File.join("images", relative_path, ["#{source&.class}", "#{source&.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
File.join("images/avatars", ["#{source&.class}", "#{source&.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
# source.get_letter_avatar_url
|
||||
|
|
|
@ -134,7 +134,7 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def jianmu_devops_url
|
||||
EduSetting.get("jianmu_devops_url") || "https://ci-v3.test.jianmuhub.com"
|
||||
EduSetting.get("jianmu_devops_url")
|
||||
end
|
||||
|
||||
|
||||
|
@ -159,6 +159,9 @@ module ProjectsHelper
|
|||
when 'kernel' then "#{url}/v1/openeuler/entropy"
|
||||
when 'opengauss-server' then "#{url}/v1/opengauss/entropy"
|
||||
when 'mindspore' then "#{url}/v1/mindspore/entropy"
|
||||
when 'openharmony' then "#{url}/api/openharmony/entropy"
|
||||
when 'openeuler' then "#{url}/api/openeuler/entropy"
|
||||
when 'xiuos' then "#{url}/api/xiuos/entropy"
|
||||
else ''
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
class ChangeIssueStatusByMessageJob < ApplicationJob
|
||||
queue_as :notify
|
||||
|
||||
# Close, Closes, Closed, Closing, close, closes, closed, closing
|
||||
# Fix, Fixes, Fixed, Fixing, fix, fixes, fixed, fixing
|
||||
# Resolve, Resolves, Resolved, Resolving, resolve, resolves, resolved, resolving
|
||||
# Implement, Implements, Implemented, Implementing, implement, implements, implemented, implementing
|
||||
# 以上关键词后接 issue_id 例如:Closes #234 Closes #123, #245, #992
|
||||
|
||||
|
||||
def get_pm_issue_data(user, org, pm_project_id, issue_id)
|
||||
url = "#{EduSetting.get("pms_server_url")}/api/pms/#{org.login}/pmsProjectIssues/#{issue_id}?pmProjectId=#{pm_project_id}"
|
||||
|
||||
headers = {
|
||||
'Cookie' => "autologin_trustie=#{Token.get_or_create_permanent_login_token(user, 'autologin')&.value}",
|
||||
}
|
||||
|
||||
response = RestClient.get(url, headers)
|
||||
|
||||
puts response.body
|
||||
return JSON.parse(response.body)["code"].to_i == 200
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def perform(commitsha, project, user, tag_issue_id_content, status_id=1)
|
||||
Rails.logger.info "需要操作的issue_id内容为 #{tag_issue_id_content}"
|
||||
tag_issue_id_content = tag_issue_id_content.gsub(/\s+/, '')
|
||||
tag_issue_id_content.to_s.split(",").each do |tag_issue|
|
||||
issue_id = tag_issue.gsub('#', '')
|
||||
issue = project.issues.issue_issue.where(project_issues_index: issue_id).where.not(id: issue_id).take || Issue.issue_issue.find_by_id(issue_id)
|
||||
next unless issue.present? # issue不存在 跳过
|
||||
next if issue.project.present? && !issue.project.member?(user) # issue归属项目,用户没有修改issue的权限,跳过
|
||||
next if issue.pm_project_id.nil? && project.id.to_i != issue.project&.id.to_i
|
||||
next if issue.pm_project_id.present? && !get_pm_issue_data(user, project.owner, issue.pm_project_id, issue.id) # issue是组织下工作项,不具备组织的访问权限,跳过
|
||||
|
||||
issue_project = issue.project || Project.new(id: 0, user_id: 0, name: 'pm_mm', identifier: 'pm_mm', is_public:true)
|
||||
if issue.pm_project_id.present?
|
||||
Api::Pm::Issues::UpdateService.call(issue_project, issue, {status_id: status_id}, user, "Project##{project.id}@#{commitsha}")
|
||||
else
|
||||
Api::V1::Issues::UpdateService.call(issue_project, issue, {status_id: status_id}, user, "Project##{project.id}@#{commitsha}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,6 +6,7 @@ class OpenProjectDevOpsJob < ApplicationJob
|
|||
def perform(project_id, user_id)
|
||||
project = Project.find_by(id: project_id)
|
||||
return if project.blank?
|
||||
return if EduSetting.get("jianmu_devops_url").blank?
|
||||
user = User.find_by(id: user_id)
|
||||
code = jianmu_devops_code(project, user)
|
||||
uri = URI.parse("#{jianmu_devops_url}/activate?code=#{URI.encode_www_form_component(code)}")
|
||||
|
|
|
@ -4,6 +4,7 @@ class UpdateProjectTopicJob < ApplicationJob
|
|||
queue_as :message
|
||||
|
||||
def perform(project_id)
|
||||
return unless $redis_cache.set("UpdateProjectTopicJob:#{project_id}", 1, nx: true, ex: 10.seconds)
|
||||
project = Project.find_by(id: project_id)
|
||||
return if project.blank?
|
||||
begin
|
||||
|
@ -25,7 +26,9 @@ class UpdateProjectTopicJob < ApplicationJob
|
|||
topic_count +=1
|
||||
end
|
||||
end
|
||||
$redis_cache.del("UpdateProjectTopicJob:#{project_id}")
|
||||
rescue => e
|
||||
$redis_cache.del("UpdateProjectTopicJob:#{project_id}")
|
||||
puts "get_repos_languages: error:#{e.message}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
require 'oauth2'
|
||||
|
||||
module Ci4s::Service
|
||||
module_function
|
||||
|
||||
def client_id
|
||||
config = Rails.application.config_for(:configuration)
|
||||
config.dig("oauth", "ci4s", "client_id")
|
||||
end
|
||||
|
||||
def client_secret
|
||||
config = Rails.application.config_for(:configuration)
|
||||
config.dig("oauth", "ci4s", "client_secret")
|
||||
end
|
||||
|
||||
def base_url
|
||||
config = Rails.application.config_for(:configuration)
|
||||
config.dig("oauth", "ci4s", "base_url")
|
||||
end
|
||||
|
||||
def redirect_uri
|
||||
config = Rails.application.config_for(:configuration)
|
||||
config.dig("oauth", "ci4s", "redirect_uri")
|
||||
end
|
||||
|
||||
def oauth_url
|
||||
"#{base_url}/oauth/authorize?client_id=#{client_id}&redirect_uri=#{URI.encode_www_form_component(redirect_uri)}&response_type=code&grant_type=authorization_code"
|
||||
end
|
||||
|
||||
def request(method, url, params)
|
||||
begin
|
||||
Rails.logger.info("[Ci4sOauth] [#{method.to_s.upcase}] #{url} || #{params}")
|
||||
|
||||
client ||= begin
|
||||
Faraday.new(url: base_url) do |req|
|
||||
req.request :url_encoded
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.response :logger # 显示日志
|
||||
req.adapter Faraday.default_adapter
|
||||
req.authorization :Bearer, params[:access_token]
|
||||
req.headers['Authorization']
|
||||
end
|
||||
end
|
||||
response = client.public_send(method, url, params)
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
Rails.logger.info("[Ci4sOauth] [#{response.status}] #{result}")
|
||||
|
||||
result
|
||||
rescue Exception => e
|
||||
raise Gitlink::TipException.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def access_token(code)
|
||||
begin
|
||||
Rails.logger.info("[Ci4sOauth] [code] #{code} ")
|
||||
Rails.logger.info("[Ci4sOauth] [redirect_uri] #{redirect_uri} ")
|
||||
client = OAuth2::Client.new(client_id, client_secret, site: base_url)
|
||||
result = client.auth_code.get_token(code, redirect_uri: redirect_uri).to_hash
|
||||
return result
|
||||
rescue Exception => e
|
||||
raise Gitlink::TipException.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def user_info(access_token)
|
||||
request(:get, '/user/info', {access_token: access_token})
|
||||
end
|
||||
end
|
|
@ -17,11 +17,15 @@
|
|||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# label :string(255)
|
||||
# node_type :string(255)
|
||||
# is_mutil_link :boolean
|
||||
# link_type :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_action_nodes_on_action_node_types_id (action_node_types_id)
|
||||
# index_action_nodes_on_user_id (user_id)
|
||||
# by_name (name)
|
||||
# index_action_nodes_on_action_types_id (action_node_types_id)
|
||||
# index_action_nodes_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class Action::Node < ApplicationRecord
|
||||
|
@ -34,7 +38,7 @@ class Action::Node < ApplicationRecord
|
|||
|
||||
belongs_to :user, optional: true
|
||||
|
||||
attr_accessor :cust_name, :run_values, :input_values
|
||||
attr_accessor :cust_name, :run_values, :input_values, :parent_node_id, :sub_nodes, :link_type_array, :node_id
|
||||
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :full_name, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
|
@ -42,6 +46,7 @@ class Action::Node < ApplicationRecord
|
|||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
|
||||
|
||||
def content_yaml
|
||||
"foo".to_yaml
|
||||
<<~YAML
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: action_pipeline_results
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# run_id :integer
|
||||
# step_id :string(255)
|
||||
# job_name :string(255)
|
||||
# job_show_type :string(255)
|
||||
# job_result :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_action_pipeline_results_on_project_id (project_id)
|
||||
# index_action_pipeline_results_on_run_id (run_id)
|
||||
#
|
||||
|
||||
class Action::PipelineResult < ApplicationRecord
|
||||
self.table_name = 'action_pipeline_results'
|
||||
belongs_to :project
|
||||
end
|
||||
|
|
@ -16,8 +16,9 @@
|
|||
|
||||
|
||||
class EduSetting < ApplicationRecord
|
||||
after_commit :expire_value_cache
|
||||
validates_uniqueness_of :name, message: "【%{value}】标识已被使用"
|
||||
after_commit :expire_value_cache, on: [:create, :update]
|
||||
after_commit :clear_value_cache, on: :destroy
|
||||
|
||||
scope :by_search, -> (keyword){ where("name LIKE :keyword OR value LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? }
|
||||
|
||||
|
@ -26,7 +27,11 @@ class EduSetting < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.get(key)
|
||||
Rails.cache.fetch(value_cache_key(key), expires_in: 1.days) do
|
||||
begin
|
||||
Rails.cache.fetch(value_cache_key(key), expires_in: 1.days) do
|
||||
find_by_name(key.to_s)&.value
|
||||
end
|
||||
rescue Exception => e
|
||||
find_by_name(key.to_s)&.value
|
||||
end
|
||||
end
|
||||
|
@ -42,4 +47,8 @@ class EduSetting < ApplicationRecord
|
|||
def expire_value_cache
|
||||
Rails.cache.write(value_cache_key, value)
|
||||
end
|
||||
|
||||
def clear_value_cache
|
||||
Rails.cache.delete(value_cache_key)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class Gitea::ActionRun < Gitea::Base
|
||||
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
|
||||
# establish_connection :gitea_db
|
||||
|
||||
self.table_name = "action_run"
|
||||
|
||||
# belongs_to :user, class_name: '::User', primary_key: :gitea_uid, foreign_key: :owner_id, optional: true
|
||||
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class Gitea::RepoUnit < Gitea::Base
|
||||
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
|
||||
# establish_connection :gitea_db
|
||||
|
||||
self.table_name = "repo_unit"
|
||||
|
||||
# belongs_to :user, class_name: '::User', primary_key: :gitea_uid, foreign_key: :owner_id, optional: true
|
||||
|
||||
end
|
|
@ -103,6 +103,7 @@ class Issue < ApplicationRecord
|
|||
scope :issue_issue, ->{where(issue_classify: [nil, 'issue'])}
|
||||
scope :issue_pull_request, ->{where(issue_classify: 'pull_request')}
|
||||
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
|
||||
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)}
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
# resolveer_id :integer
|
||||
# need_respond :boolean default("0")
|
||||
# updated_on :datetime
|
||||
# operate_by :string(255) default("Issue")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
@ -52,6 +53,7 @@ class Journal < ApplicationRecord
|
|||
scope :journal_includes, ->{includes(:user, :journal_details, :attachments)}
|
||||
scope :parent_journals, ->{where(parent_id: nil)}
|
||||
scope :children_journals, lambda{|journal_id| where(parent_id: journal_id)}
|
||||
scope :operate_journals, ->{where(notes: nil)}
|
||||
|
||||
enum state: {opened: 0, resolved: 1, disabled: 2}
|
||||
|
||||
|
@ -83,6 +85,17 @@ class Journal < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def operate_by_content
|
||||
return '' if self.operate_by == "Issue"
|
||||
if self.operate_by.starts_with?("Project#")
|
||||
project_id, commit_sha = self.operate_by.scan(/#(\d+).*?@(\w+)/)[0]
|
||||
project =Project.find_by_id(project_id)
|
||||
return "通过 #{project&.owner&.real_name}/#{project&.name} 提交 <a href=\"#{Rails.application.config_for(:configuration)['platform_url']}/#{project&.owner&.login}/#{project&.identifier}/commits/#{commit_sha}\">#{commit_sha[0...10]}</a>"
|
||||
end
|
||||
rescue
|
||||
return ''
|
||||
end
|
||||
|
||||
def pm_operate_category
|
||||
detail = self.journal_details.take
|
||||
if %w(requirement task bug).include?(detail.property) && detail.prop_key.to_s == "1"
|
||||
|
@ -92,8 +105,23 @@ class Journal < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def pm_dashboard_operate_content
|
||||
content = self.pm_operate_content
|
||||
if content.start_with?('创建了')
|
||||
content += "<b>#{self.issue.subject}</b>"
|
||||
else
|
||||
prefix = '将'
|
||||
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>"
|
||||
content = prefix + content.sub('将', '的')
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def pm_operate_content
|
||||
content = ""
|
||||
content = "#{operate_by_content}"
|
||||
detail = self.journal_details.take
|
||||
case detail.property
|
||||
when 'requirement'
|
||||
|
@ -154,7 +182,7 @@ class Journal < ApplicationRecord
|
|||
end
|
||||
return content
|
||||
else
|
||||
return "创建了需求"
|
||||
content += "创建了需求"
|
||||
end
|
||||
when 'task'
|
||||
case detail.prop_key
|
||||
|
@ -214,7 +242,7 @@ class Journal < ApplicationRecord
|
|||
end
|
||||
return content
|
||||
else
|
||||
return "创建了任务"
|
||||
content += "创建了任务"
|
||||
end
|
||||
when 'bug'
|
||||
case detail.prop_key
|
||||
|
@ -274,14 +302,14 @@ class Journal < ApplicationRecord
|
|||
end
|
||||
return content
|
||||
else
|
||||
return "创建了缺陷"
|
||||
content += "创建了缺陷"
|
||||
end
|
||||
when 'attr'
|
||||
case detail.prop_key
|
||||
when 'subject'
|
||||
return "修改了<b>标题</b>"
|
||||
content += "修改了<b>标题</b>"
|
||||
when 'description'
|
||||
return "修改了<b>正文</b>"
|
||||
content += "修改了<b>正文</b>"
|
||||
when 'priority_id'
|
||||
old_value = IssuePriority.find_by_id(detail.old_value)&.name
|
||||
new_value = IssuePriority.find_by_id(detail.value)&.name
|
||||
|
@ -491,21 +519,23 @@ class Journal < ApplicationRecord
|
|||
issue = self.issue
|
||||
case issue.pm_issue_type
|
||||
when 1
|
||||
return "创建了需求"
|
||||
content += "创建了需求"
|
||||
when 2
|
||||
return "创建了任务"
|
||||
content += "创建了任务"
|
||||
when 3
|
||||
return "创建了缺陷"
|
||||
content += "创建了缺陷"
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
def operate_content
|
||||
content = ""
|
||||
content = "#{operate_by_content}"
|
||||
detail = self.journal_details.take
|
||||
case detail.property
|
||||
when 'issue'
|
||||
return "创建了<b>疑修</b>"
|
||||
content += "创建了<b>疑修</b>"
|
||||
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("、")
|
||||
|
@ -534,12 +564,12 @@ class Journal < ApplicationRecord
|
|||
content += "将负责人由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
when 'attr'
|
||||
content = "将"
|
||||
content += "将"
|
||||
case detail.prop_key
|
||||
when 'subject'
|
||||
return "修改了<b>标题</b>"
|
||||
content += "修改了<b>标题</b>"
|
||||
when 'description'
|
||||
return "修改了<b>描述</b>"
|
||||
content += "修改了<b>描述</b>"
|
||||
when 'status_id'
|
||||
old_value = IssueStatus.find_by_id(detail.old_value)&.name
|
||||
new_value = IssueStatus.find_by_id(detail.value)&.name
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: open_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# type :string(255)
|
||||
# uid :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# extra :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_open_users_on_type_and_uid (type,uid) UNIQUE
|
||||
# index_open_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class OpenUsers::Ci4s < OpenUser
|
||||
def nickname
|
||||
extra&.[]('username')
|
||||
end
|
||||
|
||||
def en_type
|
||||
'ci4s'
|
||||
end
|
||||
end
|
|
@ -19,4 +19,8 @@ class ProjectTopicRalate < ApplicationRecord
|
|||
belongs_to :project_topic, counter_cache: :projects_count
|
||||
belongs_to :project
|
||||
|
||||
|
||||
validates :project_id, uniqueness: { scope: :project_topic_id }
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -36,7 +36,7 @@ class PullRequest < ApplicationRecord
|
|||
|
||||
belongs_to :issue
|
||||
belongs_to :user
|
||||
belongs_to :project, counter_cache: true, touch: true
|
||||
belongs_to :project, counter_cache: true, touch: true, optional: true
|
||||
belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id, optional: true
|
||||
has_many :pull_request_assigns, foreign_key: :pull_request_id
|
||||
has_many :pull_request_tags, foreign_key: :pull_request_id
|
||||
|
|
|
@ -137,7 +137,7 @@ class User < Owner
|
|||
has_many :tidings, :dependent => :destroy
|
||||
# has_many :journals_for_messages, :as => :jour, :dependent => :destroy
|
||||
|
||||
has_many :attachments,foreign_key: :author_id, :dependent => :destroy
|
||||
has_many :attachments,foreign_key: :author_id
|
||||
|
||||
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy
|
||||
|
||||
|
@ -160,7 +160,7 @@ class User < Owner
|
|||
|
||||
# 教学案例
|
||||
# has_many :libraries, dependent: :destroy
|
||||
has_many :project_trends, dependent: :destroy
|
||||
has_many :project_trends
|
||||
has_many :oauths , dependent: :destroy
|
||||
has_many :apply_signatures, dependent: :destroy
|
||||
|
||||
|
@ -169,8 +169,8 @@ class User < Owner
|
|||
has_many :pinned_projects, dependent: :destroy
|
||||
has_many :is_pinned_projects, through: :pinned_projects, source: :project
|
||||
accepts_nested_attributes_for :is_pinned_projects
|
||||
has_many :issues, dependent: :destroy, foreign_key: :author_id
|
||||
has_many :pull_requests, dependent: :destroy
|
||||
has_many :issues, foreign_key: :author_id
|
||||
has_many :pull_requests
|
||||
has_many :public_keys, class_name: "Gitea::PublicKey",primary_key: :gitea_uid, foreign_key: :owner_id, dependent: :destroy
|
||||
|
||||
has_one :user_template_message_setting, dependent: :destroy
|
||||
|
@ -690,9 +690,13 @@ class User < Owner
|
|||
end
|
||||
|
||||
# Returns the user who matches the given autologin +key+ or nil
|
||||
def self.try_to_autologin(key,type)
|
||||
user = Token.find_active_user(type, key)
|
||||
user.update(last_login_on: Time.now) if user
|
||||
def self.try_to_autologin(key)
|
||||
user = Token.find_active_user('autologin', key)
|
||||
if user
|
||||
Rails.cache.fetch("user::update::last_login_on::#{user.id}",:expires_in => 5.minutes) do
|
||||
user.update(last_login_on: Time.now)
|
||||
end
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
# updated_at :datetime not null
|
||||
# ip :string(255)
|
||||
# data_bank :text(65535)
|
||||
# login :string(255)
|
||||
# phone :string(255)
|
||||
# email :string(255)
|
||||
# memo :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
@ -22,4 +26,75 @@
|
|||
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 "DestroyProject" then "删除项目"
|
||||
when "Login" then "登录"
|
||||
when "Logout" then "退出登录"
|
||||
else self.action_type
|
||||
end
|
||||
end
|
||||
|
||||
def opt_user_name
|
||||
user = User.find_by(id: self.user_id)
|
||||
if user.present?
|
||||
user&.login
|
||||
else
|
||||
del_user = UserAction.find_by(action_type: "DestroyUser", action_id: self.user_id)
|
||||
del_user.present? ? del_user.user.login : "不存在用户:#{user_id}"
|
||||
end
|
||||
end
|
||||
|
||||
def action_info
|
||||
case action_type
|
||||
when "DestroyUser" then "账号:#{user&.login}<br/>邮箱:#{user&.mail}<br/>手机号:#{user&.phone}<br/>昵称:#{user&.nickname}<br/>"
|
||||
when "DestroyProject" then "项目名称:#{project&.name}<br/>项目标识:#{project&.identifier}<br/>"
|
||||
else "--"
|
||||
end
|
||||
end
|
||||
|
||||
def user
|
||||
action_user = if action_type == "DestroyUser" && data_bank.present?
|
||||
build_mode("User")
|
||||
else
|
||||
User.find_by(id: self.user_id)
|
||||
end
|
||||
action_user
|
||||
end
|
||||
|
||||
def project
|
||||
action_project = if action_type == "DestroyProject" && data_bank.present?
|
||||
build_mode("Project")
|
||||
else
|
||||
Project.find_by(id: self.action_id)
|
||||
end
|
||||
action_project
|
||||
end
|
||||
def build_mode(model_name)
|
||||
model = model_name.constantize.new
|
||||
model_name.constantize.column_names.each do |col|
|
||||
data = self.data_bank.class == String ? JSON.parse(self.data_bank) : self.data_bank
|
||||
model[col] = data[col]
|
||||
end
|
||||
model
|
||||
rescue =>err
|
||||
return nil
|
||||
end
|
||||
|
||||
private
|
||||
def add_user_info
|
||||
if self.login.blank?
|
||||
if user.present?
|
||||
self.login = user.login
|
||||
self.email = user.mail
|
||||
self.phone = user.phone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
module Accounts
|
||||
class ResetPasswordService < ApplicationService
|
||||
include AesCryptHelper
|
||||
# login、code、password、password_confirmation
|
||||
def initialize(user, params)
|
||||
@user = user
|
||||
@password = params[:password]
|
||||
@password_confirmation = params[:password_confirmation]
|
||||
@password = decrypt(params[:password]) rescue ""
|
||||
@password_confirmation = decrypt(params[:password_confirmation]) rescue ""
|
||||
end
|
||||
|
||||
def call
|
||||
|
|
|
@ -3,7 +3,7 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
include Api::V1::Issues::Concerns::Checkable
|
||||
include Api::V1::Issues::Concerns::Loadable
|
||||
|
||||
attr_reader :project, :issue, :current_user
|
||||
attr_reader :project, :issue, :current_user, :operate_by
|
||||
attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description, :blockchain_token_num
|
||||
attr_reader :target_pm_project_id, :pm_sprint_id, :pm_issue_type, :root_id, :time_scale
|
||||
attr_reader :issue_tag_ids, :assigner_ids, :attachment_ids, :receivers_login, :before_issue_tag_ids, :before_assigner_ids, :project_id
|
||||
|
@ -12,10 +12,11 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
validates :project, :issue, :current_user, presence: true
|
||||
validates :blockchain_token_num, numericality: {greater_than: 0}, allow_blank: true
|
||||
|
||||
def initialize(project, issue, params, current_user = nil)
|
||||
def initialize(project, issue, params, current_user = nil, operate_by='Issue')
|
||||
@project = project
|
||||
@issue = issue
|
||||
@current_user = current_user
|
||||
@operate_by = operate_by
|
||||
@status_id = params[:status_id]
|
||||
@priority_id = params[:priority_id]
|
||||
@milestone_id = params[:milestone_id]
|
||||
|
@ -64,7 +65,6 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
build_assigner_issue_journal_details unless assigner_ids.nil?# 操作记录
|
||||
build_attachment_issue_journal_details unless attachment_ids.nil?
|
||||
build_issue_tag_issue_journal_details unless issue_tag_ids.nil?
|
||||
build_issue_project_trends if status_id.present? # 开关时间记录
|
||||
build_assigner_participants unless assigner_ids.nil? # 负责人
|
||||
build_edit_participants
|
||||
build_atme_participants if @atme_receivers.present?
|
||||
|
@ -92,6 +92,7 @@ class Api::Pm::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_cirle_blockchain_token if blockchain_token_num.present?
|
||||
unless @project.id.zero?
|
||||
# @信息发送
|
||||
|
@ -172,7 +173,7 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
|
||||
def build_issue_project_trends
|
||||
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][1] == 5
|
||||
@updated_issue.project_trends.new({user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE})
|
||||
@updated_issue.project_trends.create!({user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE})
|
||||
end
|
||||
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][0] == 5
|
||||
@updated_issue.project_trends.where(action_type: ProjectTrend::CLOSE).each(&:destroy!)
|
||||
|
@ -183,91 +184,91 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
begin
|
||||
# 更改标题
|
||||
if @updated_issue.previous_changes["subject"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "subject", old_value: @updated_issue.previous_changes["subject"][0], value: @updated_issue.previous_changes["subject"][1]})
|
||||
end
|
||||
|
||||
# 更改描述
|
||||
if @updated_issue.previous_changes["description"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "description", old_value: @updated_issue.previous_changes["description"][0], value: @updated_issue.previous_changes["description"][1]})
|
||||
end
|
||||
|
||||
# 修改状态
|
||||
if @updated_issue.previous_changes["status_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: @updated_issue.pm_issue_type_string, prop_key: "status_id", old_value: @updated_issue.previous_changes["status_id"][0], value: @updated_issue.previous_changes["status_id"][1]})
|
||||
end
|
||||
|
||||
# 修改优先级
|
||||
if @updated_issue.previous_changes["priority_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "priority_id", old_value: @updated_issue.previous_changes["priority_id"][0], value: @updated_issue.previous_changes["priority_id"][1]})
|
||||
end
|
||||
|
||||
# 修改工作项类型
|
||||
if @updated_issue.previous_changes["pm_issue_type"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "pm_issue_type", old_value: @updated_issue.previous_changes["pm_issue_type"][0], value: @updated_issue.previous_changes["pm_issue_type"][1]})
|
||||
end
|
||||
|
||||
# 修改迭代
|
||||
if @updated_issue.previous_changes["pm_sprint_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "pm_sprint_id", old_value: @updated_issue.previous_changes["pm_sprint_id"][0], value: @updated_issue.previous_changes["pm_sprint_id"][1]})
|
||||
end
|
||||
|
||||
# 修改代码库
|
||||
if @updated_issue.previous_changes["project_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "project_id", old_value: @updated_issue.previous_changes["project_id"][0], value: @updated_issue.previous_changes["project_id"][1]})
|
||||
end
|
||||
|
||||
# 修改里程碑
|
||||
if @updated_issue.previous_changes["fixed_version_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "fixed_version_id", old_value: @updated_issue.previous_changes["fixed_version_id"][0], value: @updated_issue.previous_changes["fixed_version_id"][1]})
|
||||
end
|
||||
|
||||
# 更改分支
|
||||
if @updated_issue.previous_changes["branch_name"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "branch_name", old_value: @updated_issue.previous_changes["branch_name"][0], value: @updated_issue.previous_changes["branch_name"][1]})
|
||||
end
|
||||
|
||||
# 更改开始时间
|
||||
if @updated_issue.previous_changes["start_date"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "start_date", old_value: @updated_issue.previous_changes["start_date"][0], value: @updated_issue.previous_changes["start_date"][1]})
|
||||
end
|
||||
|
||||
# 更改结束时间
|
||||
if @updated_issue.previous_changes["due_date"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "due_date", old_value: @updated_issue.previous_changes["due_date"][0], value: @updated_issue.previous_changes["due_date"][1]})
|
||||
end
|
||||
|
||||
# 更改预估工时
|
||||
if @updated_issue.previous_changes["time_scale"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "time_scale", old_value: @updated_issue.previous_changes["time_scale"][0], value: @updated_issue.previous_changes["time_scale"][1]})
|
||||
end
|
||||
|
||||
# 更改父工作项
|
||||
if @updated_issue.previous_changes["root_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: @updated_issue.pm_issue_type_string, prop_key: "root_id", old_value: @updated_issue.previous_changes["root_id"][0], value: @updated_issue.previous_changes["root_id"][1]})
|
||||
|
||||
# 更改子工作项
|
||||
before_parent_issue = Issue.find_by_id(@updated_issue.previous_changes["root_id"][0])
|
||||
if before_parent_issue.present?
|
||||
journal = before_parent_issue.journals.create!({user_id: current_user.id})
|
||||
journal = before_parent_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: @updated_issue.pm_issue_type_string, prop_key: "tag_leaf_issue", old_value: @updated_issue.id.to_s})
|
||||
end
|
||||
|
||||
after_parent_issue = Issue.find_by_id(@updated_issue.previous_changes["root_id"][1])
|
||||
if after_parent_issue.present?
|
||||
journal = after_parent_issue.journals.create!({user_id: current_user.id})
|
||||
journal = after_parent_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: @updated_issue.pm_issue_type_string, prop_key: "tag_leaf_issue", value: @updated_issue.id.to_s})
|
||||
end
|
||||
end
|
||||
|
@ -283,7 +284,7 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
new_assigner_ids = [] if @assigner_ids.nil?
|
||||
now_assigner_ids = @updated_issue.assigners.pluck(:id)
|
||||
if !(now_assigner_ids.sort == new_assigner_ids.sort)
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "assigner", prop_key: "#{new_assigner_ids.size}", old_value: now_assigner_ids.join(","), value: new_assigner_ids.join(",")})
|
||||
end
|
||||
|
||||
|
@ -299,7 +300,7 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
new_issue_tag_ids = [] if @issue_tag_ids.nil?
|
||||
now_issue_tag_ids = @updated_issue.issue_tags.pluck(:id)
|
||||
if !(now_issue_tag_ids.sort == new_issue_tag_ids.sort)
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "issue_tag", prop_key: "#{new_issue_tag_ids.size}", old_value: now_issue_tag_ids.join(","), value: new_issue_tag_ids.join(",")})
|
||||
end
|
||||
rescue
|
||||
|
@ -315,7 +316,7 @@ class Api::Pm::Issues::UpdateService < ApplicationService
|
|||
new_attachment_ids = [] if @attachment_ids.nil?
|
||||
now_attachment_ids = @updated_issue.attachments.pluck(:id)
|
||||
if !(now_attachment_ids.sort == new_attachment_ids.sort)
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attachment", prop_key: "#{new_attachment_ids.size}", old_value: now_attachment_ids.join(","), value: new_attachment_ids.join(",")})
|
||||
end
|
||||
rescue
|
||||
|
|
|
@ -3,7 +3,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
include Api::V1::Issues::Concerns::Checkable
|
||||
include Api::V1::Issues::Concerns::Loadable
|
||||
|
||||
attr_reader :project, :issue, :current_user
|
||||
attr_reader :project, :issue, :current_user, :operate_by
|
||||
attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description, :blockchain_token_num
|
||||
attr_reader :target_pm_project_id, :pm_sprint_id, :pm_issue_type, :root_id, :time_scale
|
||||
attr_reader :issue_tag_ids, :assigner_ids, :attachment_ids, :receivers_login, :before_issue_tag_ids, :before_assigner_ids, :project_id
|
||||
|
@ -12,10 +12,11 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
validates :project, :issue, :current_user, presence: true
|
||||
validates :blockchain_token_num, numericality: {greater_than: 0}, allow_blank: true
|
||||
|
||||
def initialize(project, issue, params, current_user = nil)
|
||||
def initialize(project, issue, params, current_user = nil, operate_by='Issue')
|
||||
@project = project
|
||||
@issue = issue
|
||||
@current_user = current_user
|
||||
@operate_by = operate_by
|
||||
@status_id = params[:status_id]
|
||||
@priority_id = params[:priority_id]
|
||||
@milestone_id = params[:milestone_id]
|
||||
|
@ -64,7 +65,6 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
build_assigner_issue_journal_details unless assigner_ids.nil?# 操作记录
|
||||
build_attachment_issue_journal_details unless attachment_ids.nil?
|
||||
build_issue_tag_issue_journal_details unless issue_tag_ids.nil?
|
||||
build_issue_project_trends if status_id.present? # 开关时间记录
|
||||
build_assigner_participants unless assigner_ids.nil? # 负责人
|
||||
build_edit_participants
|
||||
build_atme_participants if @atme_receivers.present?
|
||||
|
@ -88,10 +88,12 @@ 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? # 操作记录
|
||||
build_previous_issue_changes
|
||||
build_issue_project_trends if status_id.present? # 开关时间记录
|
||||
build_cirle_blockchain_token if blockchain_token_num.present?
|
||||
unless @project.id.zero?
|
||||
# @信息发送
|
||||
|
@ -172,7 +174,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
|
||||
def build_issue_project_trends
|
||||
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][1] == 5
|
||||
@updated_issue.project_trends.new({user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE})
|
||||
@updated_issue.project_trends.create!({user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE})
|
||||
end
|
||||
if @updated_issue.previous_changes["status_id"].present? && @updated_issue.previous_changes["status_id"][0] == 5
|
||||
@updated_issue.project_trends.where(action_type: ProjectTrend::CLOSE).each(&:destroy!)
|
||||
|
@ -183,49 +185,49 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
begin
|
||||
# 更改标题
|
||||
if @updated_issue.previous_changes["subject"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "subject", old_value: @updated_issue.previous_changes["subject"][0], value: @updated_issue.previous_changes["subject"][1]})
|
||||
end
|
||||
|
||||
# 更改描述
|
||||
if @updated_issue.previous_changes["description"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "description", old_value: @updated_issue.previous_changes["description"][0], value: @updated_issue.previous_changes["description"][1]})
|
||||
end
|
||||
|
||||
# 修改状态
|
||||
if @updated_issue.previous_changes["status_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "status_id", old_value: @updated_issue.previous_changes["status_id"][0], value: @updated_issue.previous_changes["status_id"][1]})
|
||||
end
|
||||
|
||||
# 修改优先级
|
||||
if @updated_issue.previous_changes["priority_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "priority_id", old_value: @updated_issue.previous_changes["priority_id"][0], value: @updated_issue.previous_changes["priority_id"][1]})
|
||||
end
|
||||
|
||||
# 修改里程碑
|
||||
if @updated_issue.previous_changes["fixed_version_id"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "fixed_version_id", old_value: @updated_issue.previous_changes["fixed_version_id"][0], value: @updated_issue.previous_changes["fixed_version_id"][1]})
|
||||
end
|
||||
|
||||
# 更改分支
|
||||
if @updated_issue.previous_changes["branch_name"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "branch_name", old_value: @updated_issue.previous_changes["branch_name"][0], value: @updated_issue.previous_changes["branch_name"][1]})
|
||||
end
|
||||
|
||||
# 更改开始时间
|
||||
if @updated_issue.previous_changes["start_date"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "start_date", old_value: @updated_issue.previous_changes["start_date"][0], value: @updated_issue.previous_changes["start_date"][1]})
|
||||
end
|
||||
|
||||
# 更改结束时间
|
||||
if @updated_issue.previous_changes["due_date"].present?
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attr", prop_key: "due_date", old_value: @updated_issue.previous_changes["due_date"][0], value: @updated_issue.previous_changes["due_date"][1]})
|
||||
end
|
||||
rescue
|
||||
|
@ -240,7 +242,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
new_assigner_ids = [] if @assigner_ids.nil?
|
||||
now_assigner_ids = @updated_issue.assigners.pluck(:id)
|
||||
if !(now_assigner_ids & assigner_ids).empty? || !(now_assigner_ids.empty? && new_assigner_ids.empty?)
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "assigner", prop_key: "#{new_assigner_ids.size}", old_value: now_assigner_ids.join(","), value: new_assigner_ids.join(",")})
|
||||
end
|
||||
|
||||
|
@ -256,7 +258,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
new_issue_tag_ids = [] if @issue_tag_ids.nil?
|
||||
now_issue_tag_ids = @updated_issue.issue_tags.pluck(:id)
|
||||
if !(now_issue_tag_ids & new_issue_tag_ids).empty? || !(now_issue_tag_ids.empty? && new_issue_tag_ids.empty?)
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "issue_tag", prop_key: "#{new_issue_tag_ids.size}", old_value: now_issue_tag_ids.join(","), value: new_issue_tag_ids.join(",")})
|
||||
end
|
||||
rescue
|
||||
|
@ -272,7 +274,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
|
|||
new_attachment_ids = [] if @attachment_ids.nil?
|
||||
now_attachment_ids = @updated_issue.attachments.pluck(:id)
|
||||
if !(now_attachment_ids & new_attachment_ids).empty? || !(now_attachment_ids.empty? && new_attachment_ids.empty?)
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id})
|
||||
journal = @updated_issue.journals.create!({user_id: current_user.id, operate_by: @operate_by})
|
||||
journal.journal_details.create!({property: "attachment", prop_key: "#{new_attachment_ids.size}", old_value: now_attachment_ids.join(","), value: new_attachment_ids.join(",")})
|
||||
end
|
||||
rescue
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
class Api::V1::Users::DeleteUserService < ApplicationService
|
||||
attr_reader :user
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
def call
|
||||
begin
|
||||
ActiveRecord::Base.transaction do
|
||||
org_ids = TeamUser.where(user_id: @user.id).pluck(:organization_id) | OrganizationUser.where(user_id: @user.id).pluck(:organization_id)
|
||||
organizations = Organization.where(id: org_ids)
|
||||
organizations.each do |org|
|
||||
# org.team_users.joins(:team).where(user_id: @user.id, teams: {authorize: %w(owner)})
|
||||
owner_count = org.team_users.joins(:team).where(teams: {authorize: %w(owner)}).count
|
||||
# 多个owner时,仅将用户从组织移除, 一个时直接删除
|
||||
org.team_users.where(user_id: @user.id).destroy_all
|
||||
org.organization_users.where(user_id: @user.id, organization_id: org.id).destroy_all
|
||||
if owner_count == 1
|
||||
if org.team_users.joins(:team).where(user_id: @user.id, teams: { authorize: %w(owner) }).count > 0
|
||||
org.destroy!
|
||||
end
|
||||
end
|
||||
end
|
||||
@user.destroy!
|
||||
del_user_data_by_sql(@user.id)
|
||||
Gitea::User::DeleteService.call(@user.login, true)
|
||||
end
|
||||
return true
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
def del_user_data_by_sql(user_id)
|
||||
sql1 = "delete from memos where author_id=#{user_id}"
|
||||
ActiveRecord::Base.connection.execute(sql1)
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
class Api::V1::Users::Projects::ListService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :observe_user, :category, :is_public, :project_type, :sort_by, :sort_direction, :search, :current_user
|
||||
attr_reader :observe_user, :category, :is_public, :project_type, :sort_by, :sort_direction, :search, :start_at, :end_at, :current_user
|
||||
attr_accessor :queried_projects
|
||||
|
||||
validates :category, inclusion: {in: %w(all join created manage watched forked), message: "请输入正确的Category"}
|
||||
|
@ -18,6 +18,8 @@ class Api::V1::Users::Projects::ListService < ApplicationService
|
|||
@sort_by = params[:sort_by] || 'updated_on'
|
||||
@sort_direction = params[:sort_direction] || 'desc'
|
||||
@search = params[:search]
|
||||
@start_at = params[:start_at]
|
||||
@end_at = params[:end_at]
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
|
@ -53,10 +55,16 @@ class Api::V1::Users::Projects::ListService < ApplicationService
|
|||
projects = Project.from("( #{normal_projects} UNION #{org_projects} ) AS projects").distinct
|
||||
when 'watched'
|
||||
projects = projects.where.not(user_id: observe_user.id).joins(:watchers).where(watchers: {watchable_type: "Project", user_id: observe_user.id})
|
||||
projects = projects.joins(:watchers).where("watchers.created_at > ? and watchers.created_at < ?", Time.at(start_at.to_i), Time.at(end_at.to_i)) if start_at.present? && end_at.present?
|
||||
when 'only_watched'
|
||||
projects = projects.where.joins(:watchers).where(watchers: {watchable_type: "Project", user_id: observe_user.id})
|
||||
projects = projects.joins(:watchers).where("watchers.created_at > ? and watchers.created_at < ?", Time.at(start_at.to_i), Time.at(end_at.to_i)) if start_at.present? && end_at.present?
|
||||
when 'forked'
|
||||
fork_ids = observe_user.fork_users.select(:id, :fork_project_id).pluck(:fork_project_id)
|
||||
if start_at.present? && end_at.present?
|
||||
fork_ids = observe_user.fork_users.where("created_at > ? and created_at < ?", Time.at(start_at.to_i), Time.at(end_at.to_i)).select(:id, :fork_project_id).pluck(:fork_project_id)
|
||||
else
|
||||
fork_ids = observe_user.fork_users.select(:id, :fork_project_id).pluck(:fork_project_id)
|
||||
end
|
||||
projects = projects.where(id: fork_ids)
|
||||
else
|
||||
normal_projects = projects.members_projects(observe_user.id).to_sql
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Api::V1::Users::UpdateEmailService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
include AesCryptHelper
|
||||
|
||||
attr_reader :user, :token, :password, :mail, :old_mail, :code, :verify_code
|
||||
attr_accessor :gitea_data
|
||||
|
@ -10,7 +11,7 @@ class Api::V1::Users::UpdateEmailService < ApplicationService
|
|||
def initialize(user, params, token =nil)
|
||||
@user = user
|
||||
@token = token
|
||||
@password = params[:password]
|
||||
@password = decrypt(params[:password]) rescue ""
|
||||
@mail = params[:email]
|
||||
@old_mail = user.mail
|
||||
@code = params[:code]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Api::V1::Users::UpdatePhoneService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
include AesCryptHelper
|
||||
|
||||
attr_reader :user, :password, :phone, :code, :verify_code
|
||||
|
||||
|
@ -8,7 +9,7 @@ class Api::V1::Users::UpdatePhoneService < ApplicationService
|
|||
|
||||
def initialize(user, params)
|
||||
@user = user
|
||||
@password = params[:password]
|
||||
@password = decrypt(params[:password]) rescue ""
|
||||
@phone = params[:phone]
|
||||
@code = params[:code]
|
||||
@verify_code = VerificationCode.where(phone: @phone, code_type: 4).last
|
||||
|
|
|
@ -102,7 +102,7 @@ class Cache::V2::ProjectCommonService < ApplicationService
|
|||
return
|
||||
else
|
||||
load_project
|
||||
return unless @project.is_full_public
|
||||
return unless @project.present? && @project.is_full_public
|
||||
if @owner_id.present?
|
||||
if $redis_cache.hget(project_common_key, owner_id_key).nil?
|
||||
reset_project_owner_id
|
||||
|
|
|
@ -87,14 +87,22 @@ class Cache::V2::UserDateRankService < ApplicationService
|
|||
def set_user_rank
|
||||
set_user_statistic
|
||||
follow_count = $redis_cache.hget(user_date_statistic_key, "follow-count") || 0
|
||||
follow_count = follow_count.to_i < 0 ? 0 : follow_count
|
||||
pullrequest_count = $redis_cache.hget(user_date_statistic_key, "pullrequest-count") || 0
|
||||
pullrequest_count = pullrequest_count.to_i < 0 ? 0 : pullrequest_count
|
||||
issues_count = $redis_cache.hget(user_date_statistic_key, "issue-count") || 0
|
||||
issues_count = issues_count.to_i < 0 ? 0 : issues_count
|
||||
project_count = $redis_cache.hget(user_date_statistic_key, "project-count") || 0
|
||||
project_count = project_count.to_i < 0 ? 0 : project_count
|
||||
fork_count = $redis_cache.hget(user_date_statistic_key, "fork-count") || 0
|
||||
fork_count = fork_count.to_i < 0 ? 0 : fork_count
|
||||
project_watchers_count = $redis_cache.hget(user_date_statistic_key, "project-watcher-count") || 0
|
||||
project_watchers_count = project_watchers_count.to_i < 0 ? 0 : project_watchers_count
|
||||
project_praises_count = $redis_cache.hget(user_date_statistic_key, "project-praise-count") || 0
|
||||
project_praises_count = project_praises_count.to_i < 0 ? 0 : project_praises_count
|
||||
project_language = $redis_cache.hget(user_date_statistic_key, "project-language")
|
||||
project_languages_count = project_language.nil? || project_language == "{}" ? 0 : JSON.parse(project_language).length
|
||||
project_languages_count = project_languages_count.to_i < 0 ? 0 : project_languages_count
|
||||
# 影响力
|
||||
influence = (60.0 + follow_count.to_i / (follow_count.to_i + 20.0) * 40.0).to_i
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ class Gitea::Repository::Commits::ListService < Gitea::ClientService
|
|||
|
||||
private
|
||||
def params
|
||||
{ sha: args[:sha] || 'master', page: args[:page] || PAGINATE_DEFAULT_PAGE, limit: args[:limit] || PAGINATE_DEFAULT_LIMIT, token: args[:token] || "", stat: args[:page].to_i != 1 && args[:limit] !=1 }
|
||||
{ sha: args[:sha] || 'master', page: args[:page] || PAGINATE_DEFAULT_PAGE, limit: args[:limit] || PAGINATE_DEFAULT_LIMIT, token: args[:token] || "", stat: args[:page].to_i != 1 && args[:limit] !=1, files: false }
|
||||
end
|
||||
|
||||
def url
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
class Gitea::User::DeleteService < Gitea::ClientService
|
||||
attr_reader :username
|
||||
attr_reader :username, :purge
|
||||
|
||||
def initialize(username)
|
||||
def initialize(username, purge = false)
|
||||
@username = username
|
||||
@purge = purge
|
||||
end
|
||||
|
||||
def call
|
||||
|
@ -20,7 +21,7 @@ class Gitea::User::DeleteService < Gitea::ClientService
|
|||
end
|
||||
|
||||
def request_url
|
||||
"/admin/users/#{username}"
|
||||
@purge ? "/admin/users/#{username}?purge=true" : "/admin/users/#{username}"
|
||||
end
|
||||
|
||||
def params
|
||||
|
|
|
@ -31,6 +31,7 @@ class Projects::TransferService < ApplicationService
|
|||
project.members.map{|m| m.destroy! if m.user_id == owner.id || project.member(new_owner.id) || (new_owner.is_a?(Organization) && new_owner.is_member?(m.user_id)) }
|
||||
project.update!(user_id: new_owner.id)
|
||||
project.set_owner_permission(new_owner)
|
||||
project.pinned_projects.destroy_all # 移除原来精选的项目
|
||||
end
|
||||
|
||||
def update_actions
|
||||
|
|
|
@ -21,7 +21,7 @@ class Projects::VerifyAuthTokenService < ApplicationService
|
|||
private
|
||||
def regular_url
|
||||
regx = /\/\/[\s\S]*.git$/ #获取字串
|
||||
data = (regx.match @url).to_s[2..-5].split("/")
|
||||
data = (regx.match @url).to_s[2..-5].to_s.split("/")
|
||||
@website = data[0]
|
||||
@owner = data[1]
|
||||
@repo = data[2]
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
class Users::RegisterService < ApplicationService
|
||||
include AesCryptHelper
|
||||
|
||||
def initialize(params)
|
||||
@login = params[:login]
|
||||
@namespace = params[:namespace]
|
||||
@password = params[:password]
|
||||
@password = decrypt(params[:password]) rescue ""
|
||||
@code = params[:code]
|
||||
end
|
||||
|
||||
|
|
|
@ -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") %>
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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") %>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<!-- </div>-->
|
||||
<%# end %>
|
||||
<div class="form-group ">
|
||||
<label for="status">类型:</label>
|
||||
<label for="status">节点分类:</label>
|
||||
<%= form.select :action_node_types_id, options_for_select(Action::NodeType.all.map { |key| [key.name, key.id]}, node.action_node_types_id), {}, class: "form-control" %>
|
||||
</div>
|
||||
<div class="field">
|
||||
|
@ -26,6 +26,22 @@
|
|||
<%= form.label :full_name, "节点全名" %>
|
||||
<%= form.text_field :full_name %>
|
||||
</div>
|
||||
<div class="form-group ">
|
||||
<label for="status">类型:</label>
|
||||
<% node_type_options = [['action节点', 'step' ], ['启动', 'start' ], ['任务', 'job']] %>
|
||||
<%= form.select :node_type, options_for_select(node_type_options, node.node_type), {}, class: "form-control" %>
|
||||
</div>
|
||||
<div class="form-group ">
|
||||
<label for="status">是否支持分支:</label>
|
||||
<% is_mutil_link_options = [['否', false ], ['是', true]] %>
|
||||
<%= form.select :is_mutil_link, options_for_select(is_mutil_link_options, node.is_mutil_link), {}, class: "form-control" %>
|
||||
</div>
|
||||
<div class="form-group ">
|
||||
<label for="status">可连接到类型:</label>
|
||||
<% link_type_options = [Action::Node.new(name: "job", label: "任务"), Action::Node.new(name: "step", label: "action节点")] %>
|
||||
<%= collection_check_boxes(:node, :link_type_array, link_type_options, :name, :label) %>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="field">
|
||||
<%= form.label :description, "描述" %>
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
<p><a href="<%= action_templates_path %>" style="font-size: 14px;">>>前往模板配置</a></p>
|
||||
<p>说明:该界面适用于action 节点配置参数配置</p>
|
||||
|
||||
<div class="box search-form-container edu_settings-list-form">
|
||||
<%= form_tag(action_nodes_path, method: :get, class: 'form-inline search-form flex-1') do %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '关键字检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||
<% end %>
|
||||
<%= link_to "新增", new_action_node_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||
</div>
|
||||
|
||||
<table border="1" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -2,7 +2,7 @@ json.types @node_types.each do |node_type|
|
|||
if node_type.name.to_s == "未分类"
|
||||
json.extract! node_type, :id, :name
|
||||
json.nodes @no_type_nodes do |node|
|
||||
json.extract! node, :id, :label, :name, :full_name, :description, :icon, :action_node_types_id, :yaml, :sort_no, :use_count
|
||||
json.extract! node, :id, :label, :name, :full_name, :description, :icon, :action_node_types_id, :yaml, :sort_no, :use_count, :node_type, :is_mutil_link, :link_type
|
||||
json.inputs node.action_node_inputs do |node_input|
|
||||
json.partial! "node_input", locals: { node_input: node_input, node: node }
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ json.types @node_types.each do |node_type|
|
|||
else
|
||||
json.extract! node_type, :id, :name
|
||||
json.nodes node_type.action_nodes do |node|
|
||||
json.extract! node, :id, :label, :name, :full_name, :description, :icon, :action_node_types_id, :yaml, :sort_no, :use_count
|
||||
json.extract! node, :id, :label, :name, :full_name, :description, :icon, :action_node_types_id, :yaml, :sort_no, :use_count, :node_type, :is_mutil_link, :link_type
|
||||
json.inputs node.action_node_inputs do |node_input|
|
||||
json.partial! "node_input", locals: { node_input: node_input, node: node }
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
json.status 0
|
||||
json.message "success"
|
||||
|
||||
json.extract! @node, :id, :name, :full_name, :description, :action_node_types_id, :is_local, :local_url, :yaml, :sort_no, :use_count
|
||||
json.extract! @node, :id, :name, :full_name, :description, :icon, :action_node_types_id, :is_local, :local_url, :yaml, :sort_no, :use_count, :label, :node_type, :is_mutil_link, :link_type
|
||||
json.inputs @node.action_node_inputs do |node_input|
|
||||
json.partial! "node_input", locals: { node_input: node_input, node: @node }
|
||||
end
|
|
@ -17,7 +17,7 @@
|
|||
<td>
|
||||
<%= edu_setting.name %>
|
||||
</td>
|
||||
<td><%= edu_setting.value %></td>
|
||||
<td style="word-break: break-all;"><%= edu_setting.value %></td>
|
||||
|
||||
<td><%= overflow_hidden_span display_text(edu_setting.description), width: 200 %></td>
|
||||
<td><%= edu_setting.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
<tbody>
|
||||
<% if user_nps.present? %>
|
||||
<% user_nps.each_with_index do |nps, index| %>
|
||||
<tr class="user-item-<%= nps.user.id %>">
|
||||
<tr class="user-item-<%= nps.user.nil? ? "用户已注销" : nps.user.id %>">
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td class="text-left">
|
||||
<%= link_to "/#{nps.user.login}", target: '_blank' do %>
|
||||
<%= overflow_hidden_span nps.user.real_name, width: 100 %>
|
||||
<%= link_to "/#{nps.user.nil? ? "用户已注销" : nps.user.login}", target: '_blank' do %>
|
||||
<%= overflow_hidden_span (nps.user.nil? ? "用户已注销" : nps.user.real_name), width: 100 %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td><%= display_text(nps.created_at&.strftime('%Y-%m-%d %H:%M')) %></td>
|
||||
<td><%= display_text(nps.user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %></td>
|
||||
<td><%= display_text(nps.user.nil? ? "用户已注销" : nps.user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %></td>
|
||||
<td><%= nps.action_type == 'close' ? '--' : nps.score %></td>
|
||||
<td><%= nps.memo %></td>
|
||||
</tr>
|
||||
|
|
|
@ -37,6 +37,21 @@
|
|||
提升用户体验:<span class="text-danger"><%= UserNp.where("memo like '%用户体验需进一步提升%'").count %></span>,
|
||||
其他:<span class="text-danger"><%= UserNp.where("action_type !='close'").where("LENGTH(memo) >0").where.not(id: UserNp.where("memo like '%期待更加丰富的功能%' or memo like '%希望有新手引导%' or memo like '%用户体验需进一步提升%' ").ids).count %></span>
|
||||
</p>
|
||||
<p style="padding-bottom: 10px !important;">
|
||||
代码库基本功能:<span class="text-danger"><%= UserNp.where("memo like '%代码库基本功能%'").count %></span>,
|
||||
疑修:<span class="text-danger"><%= UserNp.where("memo like '%疑修%'").count %></span>,
|
||||
合并请求:<span class="text-danger"><%= UserNp.where("memo like '%合并请求%'").count %></span>,
|
||||
流水线引擎:<span class="text-danger"><%= UserNp.where("memo like '%流水线引擎%'").count %></span>,
|
||||
维基Wiki:<span class="text-danger"><%= UserNp.where("memo like '%维基Wiki%'").count %></span>,
|
||||
数据集:<span class="text-danger"><%= UserNp.where("memo like '%数据集%'").count %></span>,
|
||||
特色专区:<span class="text-danger"><%= UserNp.where("memo like '%特色专区%'").count %></span>,
|
||||
BOT功能:<span class="text-danger"><%= UserNp.where("memo like '%BOT功能%'").count %></span>,
|
||||
跨平台同步服务:<span class="text-danger"><%= UserNp.where("memo like '%跨平台同步服务%'").count %></span>,
|
||||
代码溯源及扫描服务:<span class="text-danger"><%= UserNp.where("memo like '%代码溯源及扫描服务%'").count %></span>,
|
||||
开源软件健康度量服务:<span class="text-danger"><%= UserNp.where("memo like '%开源软件健康度量服务%'").count %></span>,
|
||||
HiAgent:<span class="text-danger"><%= UserNp.where("memo like '%HiAgent%'").count %></span>,
|
||||
非常满意,没有需要吐槽的功能!:<span class="text-danger"><%= UserNp.where("memo like '%非常满意,没有需要吐槽的功能%'").count %></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="box admin-list-container users-list-container">
|
||||
<%= render partial: 'admins/nps/user_np_list', locals: { user_nps: @user_nps } %>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<div class="box search-form-container project-list-form">
|
||||
<%= form_tag(admins_projects_path, method: :get, class: 'form-inline search-form flex-1', id: 'project-list-form', remote: true) do %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '项目名称/标识检索') %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '项目ID/项目名称/标识检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||
|
||||
|
|
|
@ -26,6 +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_system_notifications_path, '系统公告配置', icon: 'bell', controller: 'admins-system_notifications', has_permission: current_user.admin? || current_user.business?) %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<% sidebar_collapse = request.cookies['admin_sidebar_collapse'].to_s == 'true' %>
|
||||
<nav id="sidebar" class="<%= sidebar_collapse ? 'active' : '' %>" data-current-controller="<%= admin_sidebar_controller %>">
|
||||
<div class="sidebar-header">
|
||||
<a href="/" class="sidebar-header-logo" data-toggle="tooltip" data-title="返回主站">
|
||||
<!-- <img class="rounded-circle" src="/images/<%#= url_to_avatar(current_user) %>" />-->
|
||||
<span class="logo-label">后台管理</span>
|
||||
</a>
|
||||
<div id="sidebarCollapse" class="navbar-btn <%= sidebar_collapse ? 'active' : '' %>">
|
||||
<i class="fa fa-chevron-left fold" data-toggle="tooltip" data-placement="right" data-boundary="window" title="收起"></i>
|
||||
<i class="fa fa-bars unfold" data-toggle="tooltip" data-placement="right" data-boundary="window" title="展开"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Links -->
|
||||
<ul class="list-unstyled components">
|
||||
<li><%= sidebar_item(admins_path, '数据概览', icon: 'dashboard', controller: 'admins-dashboards', has_permission: current_user.admin?) %></li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user', has_permission: current_user.admin?) do %>
|
||||
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users', has_permission: current_user.admin?) %></li>
|
||||
<li><%= sidebar_item(admins_organizations_path, '组织列表', icon: 'user', controller: 'admins-organizations', has_permission: current_user.admin?) %></li>
|
||||
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#projects-submenu', '开源项目', icon: 'database', has_permission: current_user.admin?) do %>
|
||||
<li><%= sidebar_item(admins_projects_path, '项目列表', icon: 'database', controller: 'admins-projects', has_permission: current_user.admin?) %></li>
|
||||
<li><%= sidebar_item(admins_project_languages_path, '项目语言', icon: 'language', controller: 'admins-project_languages', has_permission: current_user.admin?) %></li>
|
||||
<li><%= sidebar_item(admins_project_categories_path, '分类列表', icon: 'sitemap', controller: 'admins-project_categories', has_permission: current_user.admin?) %></li>
|
||||
<li><%= sidebar_item(admins_project_licenses_path, '开源许可证', icon: 'file-text-o', controller: 'admins-project_licenses', has_permission: current_user.admin?) %></li>
|
||||
<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_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>
|
||||
<li><%= sidebar_item(admins_edu_settings_path, '全局变量配置', icon: 'pencil-square', controller: 'admins-edu_settings', has_permission: current_user.admin?) %></li>
|
||||
<!-- <li><%#= sidebar_item(admins_message_templates_path, '消息模版配置', icon: 'folder', controller: 'admins-message_templates', has_permission: current_user.admin?) %></li>-->
|
||||
<li><%= sidebar_item('/admins/sidekiq', '定时任务', icon: 'bell', controller: 'root', has_permission: current_user.admin?) %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
<li><%= sidebar_item('/', '返回主站', icon: 'sign-out', controller: 'root', has_permission: current_user.admin?) %></li>
|
||||
</ul>
|
||||
</nav>
|
|
@ -0,0 +1,35 @@
|
|||
<table class="table table-hover users-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="5%" class="text-center">序号</th>
|
||||
<th width="10%">操作类型</th>
|
||||
<th width="10%" class="text-left">操作人账号</th>
|
||||
<th width="25%" class="text-left">关联基本信息</th>
|
||||
<th width="15%">操作时间</th>
|
||||
<th width="35%">原因/备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if user_actions.present? %>
|
||||
<% user_actions.each_with_index do |action, index| %>
|
||||
<tr class="user-item-<%= action.user&.id %>">
|
||||
<td class="text-center"><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= action.action_name %></td>
|
||||
<td>
|
||||
<%= link_to "/#{action.user&.login}", target: '_blank' do %>
|
||||
<%= overflow_hidden_span action.opt_user_name, width: 100 %>
|
||||
<% end %></td>
|
||||
<td>
|
||||
<%= raw action.action_info %>
|
||||
</td>
|
||||
<td><%= display_text(action.created_at&.strftime('%Y-%m-%d %H:%M')) %></td>
|
||||
<td><%= action.memo %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: user_actions } %>
|
|
@ -0,0 +1,33 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('操作记录', admins_user_actions_path) %>
|
||||
<% end %>
|
||||
|
||||
<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']] %>
|
||||
<%= 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(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '操作人用户名/邮箱/手机号检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="box admin-list-container users-list-container">
|
||||
<%= render partial: 'admins/user_actions/user_action_list', locals: { user_actions: @user_actions } %>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
$('#action_type_select').change(function () {
|
||||
var switch_value = $(this).val();
|
||||
$('#action_type').val(switch_value);
|
||||
if (switch_value == ''){
|
||||
$('#action_type').show();
|
||||
}else{
|
||||
$('#action_type').hide();
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
$('.users-list-container').html("<%= j( render partial: 'admins/user_actions/user_action_list', locals: { user_actions: @user_actions } ) %>");
|
|
@ -0,0 +1,11 @@
|
|||
json.status 0
|
||||
json.message "success"
|
||||
json.data do
|
||||
json.total_count @issues.total_count
|
||||
json.my_assign_requirements_count @my_assign_requirements_count
|
||||
json.my_assign_tasks_count @my_assign_tasks_count
|
||||
json.my_assign_bugs_count @my_assign_bugs_count
|
||||
json.issues @issues.each do |issue|
|
||||
json.partial! "api/v1/issues/simple_detail", locals: {issue: issue}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
json.status 0
|
||||
json.message "success"
|
||||
json.data do
|
||||
json.total_count @journals.total_count
|
||||
json.journals @journals do |journal|
|
||||
journal.associate_attachment_container
|
||||
json.id journal.id
|
||||
json.is_journal_detail journal.is_journal_detail?
|
||||
json.created_at journal.created_on.strftime("%Y-%m-%d %H:%M")
|
||||
json.updated_at journal.updated_on.strftime("%Y-%m-%d %H:%M")
|
||||
json.created_time journal.created_on.to_i
|
||||
json.updated_time journal.updated_on.to_i
|
||||
json.user do
|
||||
if journal.user.present?
|
||||
json.partial! "api/v1/users/simple_user", user: journal.user
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
end
|
||||
detail = journal.journal_details.take
|
||||
json.operate_category journal.pm_operate_category
|
||||
json.operate_content journal.is_journal_detail? ? journal.pm_dashboard_operate_content : nil
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
json.status 0
|
||||
json.message "success"
|
||||
json.data do
|
||||
json.total_count @issues.total_count
|
||||
|
||||
json.issues @issues.each do |issue|
|
||||
json.partial! "api/v1/issues/simple_detail", locals: {issue: issue}
|
||||
end
|
||||
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue