FIX merge develop branch

This commit is contained in:
Jasder 2020-11-27 11:00:37 +08:00
commit 8facfc96e4
2692 changed files with 16398 additions and 5057590 deletions

4
.gitignore vendored
View File

@ -14,7 +14,6 @@
# mac
*.DS_Store
.bashrc
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
@ -42,6 +41,7 @@ public/react/yarn.lock
/public/react/config/stats.json
/public/react/stats.json
/public/react/.idea/*
/public/react/build/*
/public/h5build
/public/npm-debug.log
@ -66,6 +66,7 @@ vendor/bundle/
/Users
/files
/public/images/avatars
/public/cache_repository
/public/files
/workspace
/log
@ -80,3 +81,4 @@ docker/
educoder.sql
redis_data/
Dockerfile
dump.rdb

1
.rspec Normal file
View File

@ -0,0 +1 @@
--require spec_helper

View File

@ -11,4 +11,4 @@ steps:
image: ruby
commands:
- bundle install --jobs=3 --retry=3
- rake
- rake

14
Gemfile
View File

@ -19,8 +19,6 @@ gem 'kaminari', '~> 1.1', '>= 1.1.1'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'gitlab', path: 'lib/gitlab-cli'
gem 'chinese_pinyin'
gem 'rack-cors'
@ -40,7 +38,7 @@ gem 'oauth2'
#导出为pdf
gem 'pdfkit'
gem 'wkhtmltopdf-binary'
gem 'request_store'
# gem 'request_store'
#gem 'iconv'
# markdown 转html
gem 'redcarpet', '~> 3.4'
@ -55,16 +53,26 @@ gem 'ancestry'
gem 'acts_as_list'
gem 'omniauth-cas'
# profiler Middleware
gem 'rack-mini-profiler'
# object-based searching
gem 'ransack'
group :development, :test do
gem 'rspec-rails', '~> 3.8'
end
group :development do
gem 'prettier'
gem 'rubocop', '~> 0.52.0'
gem 'solargraph', '~> 0.38.0'
gem 'awesome_print'
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem "annotate", "~> 2.6.0"
end
group :test do

View File

@ -1,10 +1,3 @@
PATH
remote: lib/gitlab-cli
specs:
gitlab (3.2.0)
httparty
terminal-table
GEM
remote: https://gems.ruby-china.com/
specs:
@ -61,9 +54,13 @@ GEM
public_suffix (>= 2.0.2, < 5.0)
ancestry (3.0.7)
activerecord (>= 3.2.0)
annotate (2.6.5)
activerecord (>= 2.3.0)
rake (>= 0.8.7)
archive-zip (0.12.0)
io-like (~> 0.3.0)
arel (9.0.0)
ast (2.4.0)
autoprefixer-rails (9.7.4)
execjs
awesome_print (1.8.0)
@ -75,6 +72,8 @@ GEM
axlsx_rails (0.5.2)
actionpack (>= 3.1)
axlsx (>= 2.0.1)
backport (1.1.2)
benchmark (0.1.0)
bindex (0.8.1)
bootsnap (1.4.6)
msgpack (~> 1.0)
@ -107,6 +106,7 @@ GEM
activerecord (>= 3.1.0, < 7)
diff-lcs (1.3)
diffy (3.3.0)
e2mmap (0.1.0)
elasticsearch (7.5.0)
elasticsearch-api (= 7.5.0)
elasticsearch-transport (= 7.5.0)
@ -134,12 +134,10 @@ GEM
harmonious_dictionary (0.0.1)
hashie (3.6.0)
htmlentities (4.3.4)
httparty (0.18.0)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
io-like (0.3.1)
jaro_winkler (1.5.4)
jbuilder (2.10.0)
activesupport (>= 5.0.0)
jquery-rails (4.3.5)
@ -170,10 +168,8 @@ GEM
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
maruku (0.7.3)
method_source (0.9.2)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.1009)
mimemagic (0.3.4)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
@ -205,13 +201,21 @@ GEM
oauth2 (~> 1.1)
omniauth (~> 1.9)
parallel (1.19.1)
parser (2.7.1.1)
ast (~> 2.4.0)
pdfkit (0.8.4.1)
polyamorous (2.3.2)
activerecord (>= 5.2.1)
popper_js (1.16.0)
powerpack (0.1.2)
prettier (0.18.2)
public_suffix (4.0.3)
puma (3.12.2)
rack (2.0.9)
rack-cors (1.1.1)
rack (>= 2.0.0)
rack-mini-profiler (2.0.1)
rack (>= 1.2.0)
rack-protection (2.0.8.1)
rack
rack-test (1.1.0)
@ -243,7 +247,13 @@ GEM
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rainbow (3.0.0)
rake (13.0.1)
ransack (2.3.2)
activerecord (>= 5.2.1)
activesupport (>= 5.2.1)
i18n
polyamorous (= 2.3.2)
rb-fsevent (0.10.3)
rb-inotify (0.10.1)
ffi (~> 1.0)
@ -269,6 +279,8 @@ GEM
regexp_parser (1.7.0)
request_store (1.5.0)
rack (>= 1.4)
reverse_markdown (1.4.0)
nokogiri
roo (2.8.3)
nokogiri (~> 1)
rubyzip (>= 1.3.0, < 3.0.0)
@ -298,7 +310,15 @@ GEM
rspec-mocks (~> 3.9.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.2)
rubocop (0.52.1)
parallel (~> 1.10)
parser (>= 2.4.0.2, < 3.0)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-ole (1.2.12.2)
ruby-progressbar (1.10.1)
ruby2_keywords (0.0.2)
ruby_dep (1.5.0)
rubyzip (1.3.0)
@ -344,6 +364,20 @@ GEM
rack (~> 2.0)
rack-protection (= 2.0.8.1)
tilt (~> 2.0)
solargraph (0.38.6)
backport (~> 1.1)
benchmark
bundler (>= 1.17.2)
e2mmap
jaro_winkler (~> 1.5)
maruku (~> 0.7, >= 0.7.3)
nokogiri (~> 1.9, >= 1.9.1)
parser (~> 2.3)
reverse_markdown (~> 1.0, >= 1.0.5)
rubocop (~> 0.52)
thor (~> 1.0)
tilt (~> 2.0)
yard (~> 0.9)
spreadsheet (1.2.6)
ruby-ole (>= 1.0)
spring (2.0.2)
@ -358,8 +392,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)
@ -382,6 +414,7 @@ GEM
wkhtmltopdf-binary (0.12.5.4)
xpath (3.2.0)
nokogiri (~> 1.8)
yard (0.9.24)
PLATFORMS
ruby
@ -392,6 +425,7 @@ DEPENDENCIES
acts-as-taggable-on (~> 6.0)
acts_as_list
ancestry
annotate (~> 2.6.0)
awesome_print
axlsx (~> 3.0.0.pre)
axlsx_rails (~> 0.5.2)
@ -407,7 +441,6 @@ DEPENDENCIES
enumerize
faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0)
gitlab!
grape-entity (~> 0.7.1)
groupdate (~> 4.1.0)
harmonious_dictionary (~> 0.0.1)
@ -422,10 +455,13 @@ DEPENDENCIES
omniauth-oauth2 (~> 1.6.0)
parallel (~> 1.19, >= 1.19.1)
pdfkit
prettier
puma (~> 3.11)
rack-cors
rack-mini-profiler
rails (~> 5.2.0)
rails-i18n (~> 5.1)
ransack
rchardet (~> 1.8)
redcarpet (~> 3.4)
redis-rails
@ -434,6 +470,7 @@ DEPENDENCIES
rqrcode (~> 0.10.1)
rqrcode_png
rspec-rails (~> 3.8)
rubocop (~> 0.52.0)
ruby-ole
rubyzip
sass-rails (~> 5.0)
@ -443,6 +480,7 @@ DEPENDENCIES
simple_form
simple_xlsx_reader
sinatra
solargraph (~> 0.38.0)
spreadsheet
spring
spring-watcher-listen (~> 2.0.0)
@ -456,4 +494,4 @@ RUBY VERSION
ruby 2.3.7p456
BUNDLED WITH
2.0.2
2.1.4

View File

@ -1,4 +1,4 @@
Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台
Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台
## 特性
@ -11,13 +11,13 @@ Trustie (确实)是一个以大众化协同开发、开放式资源共享、
## 部署
#### 1. 安装依赖包
### 1. 安装依赖包
```bash
bundle install
```
#### 2. 配置初始化文件
### 2. 配置初始化文件
进入项目根目录执行一下命令:
```bash
@ -27,38 +27,71 @@ touch config/redis.yml
touch config/elasticsearch.yml
```
#### 3. 创建数据库
### 3. 配置gitea服务(可选)
**如需要部署自己的gitea平台请参考gitea官方平台https://docs.gitea.io/zh-cn/install-from-binary/**
**因目前gitea平台api受限暂时推荐从forge平台获取gitea部署文件进行部署https://forgeplus.trustie.net/projects/6070/coders**
#### 配置gitea服务步骤
1. 部署gitea服务并注册root账户
2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址
```ruby
gitea:
access_key_id: 'root'
access_key_secret: 'password'
domain: 'http://www.gitea.example.com'
base_url: '/api/v1'
```
### 4. 安装redis环境
**请自行搜索各平台如何安装部署redis环境**
### 5. 创建数据库
```bash
rails db:create
```
#### 4. 导入数据表结构
### 6. 导入数据表结构
```bash
bundle exec rake sync_table_structure:import_csv
```
#### 5. 执行migrate迁移文件
### 7. 执行migrate迁移文件
**开发环境为development 生成环境为production**
```bash
rails db:migrate RAILS_ENV=development
```
#### 6. 启动rails服务
### 8. 启动redis(此处已mac系统为例)
```bash
redis-server&
```
### 9. 启动sidekiq
**开发环境为development 生成环境为production**
```bash
bundle exec sidekiq -C config/sidekiq.yml -e production -d
```
### 10. 启动rails服务
```bash
rails s
```
#### 7. 浏览器访问
### 11. 浏览器访问
在浏览器中输入如下地址访问:
```bash
http://localhost:3000/projects
http://localhost:3000/
```
## 页面展示
- 代码库
- 代码库
![](docs/figs/code.png)
@ -70,13 +103,10 @@ http://localhost:3000/projects
![](docs/figs/issue_view.png)
- 任务指派
- 任务指派
![](docs/figs/issue_assign2.png)
- 里程碑
![](docs/figs/milestone.png)

3601
api_document.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);

View File

@ -0,0 +1,13 @@
App.mirror_project = App.cable.subscriptions.create("MirrorProjectChannel", {
connected: function() {
// Called when the subscription is ready for use on the server
},
disconnected: function() {
// Called when the subscription has been terminated by the server
},
received: function(data) {
// Called when there's incoming data on the websocket for this channel
}
});

View File

@ -135,5 +135,6 @@
padding: 10px 20px 0;
background: #fff;
}
.mt-10{margin-top: 10px;}
}

View File

@ -0,0 +1,78 @@
html{margin:0px;padding: 0px;font-size: 14px;font-family: "微软雅黑","宋体";}
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td {
margin: 0;
padding: 0;
}
.IndexContent{
height: 100vh;
width: 100%;
position: relative;
background-image: url('/images/oauth/backImg.png');
background-repeat: no-repeat;
background-size: cover;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.indexLogo{
width:80px;
margin-bottom: 35px;
}
.indexPanel{
width: 580px;
min-height: 400px;
background-color: #fff;
box-shadow: 0px 2px 10px 5px rgba(0,0,0,0.05);
border-radius: 5px;
box-sizing: border-box;
}
.indexTitle{
height: 75px;
line-height: 75px;
font-size: 18px;
color:#333;
text-align: center;
border-bottom: 1px solid #eee;
}
.indexInfo{
display: flex;
flex-direction: column;
align-items: flex-start;
}
.indexInfos{
padding:40px 60px;
}
.indexInfo > span{
color: #333;
font-size: 16px;
margin-top: 5px;
}
.indexInfo input{
width: 100%;
height:40px;
border-radius: 2px;
border:1px solid #eee;
margin-top: 5px;
padding:0px 0px 0px 8px;
outline: none;
}
.indexInfo .checkInfo{
height: 15px;
color: red;
}
.indexBtn{
text-align: center;
margin-top: 20px;
}
.indexSubmit{
width: 50%;
height: 32px;
line-height: 32px;
background-color: #1890FF;
border:none;
color: #fff;
border-radius: 2px;
cursor: pointer;
outline: none;
}

View File

@ -1,4 +1,21 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.id
end
private
def find_verified_user
puts "############### cookies.signed[:user_id]: #{cookies.signed[:user_id]}"
if current_user = User.find_by(id: cookies.signed[:user_id])
puts "############### find_verified_user success! ###############"
current_user
else
reject_unauthorized_connection
end
end
end
end

View File

@ -0,0 +1,11 @@
class MirrorProjectChannel < ApplicationCable::Channel
def subscribed
Rails.logger.info "################### channel params: #{params}"
stream_from "channel_room_#{params[:id]}"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
Rails.logger.info "################### unsubscribed ################### "
end
end

View File

@ -1,8 +1,13 @@
class AdminConstraint
def matches?(request)
laboratory = Laboratory.first
return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
user && user.admin?
if Rails.env.development?
true
else
laboratory = Laboratory.first
return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"]
user && user.admin?
end
end
end

View File

@ -13,23 +13,12 @@ class AccountsController < ApplicationController
password = params[:password]
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
@user = User.new(admin: false, login: username, mail: email, type: "User")
@user.password = password
@user.platform = platform
@user.activate
ActiveRecord::Base.transaction do
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
if interactor.success?
gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.new(username, password).call
@user.gitea_token = result['sha1']
@user.gitea_uid = gitea_user['id']
if @user.save!
render_ok({user: {id: @user.id, token: @user.gitea_token}})
end
result = autologin_register(username, email, password, platform)
if result[:message].blank?
render_ok({user: result[:user]})
else
render_error(interactor.error)
render_error(result[:message])
end
end
rescue Exception => e
@ -37,38 +26,117 @@ class AccountsController < ApplicationController
tip_exception(-1, e.message)
end
# 其他平台修改用户的信息,这边同步修改
def remote_update
ActiveRecord::Base.transaction do
user_params = params[:user_params]
user_extension_params = params[:user_extension_params]
u = User.find_by(login: params[:old_user_login])
user_mail = u.try(:mail)
if u.present?
ue = u.user_extension
u.login = user_params["login"] if user_params["login"]
u.mail = user_params["mail"] if user_params["mail"]
u.lastname = user_params["lastname"] if user_params["lastname"]
ue.gender = user_extension_params["gender"]
ue.school_id = user_extension_params["school_id"]
ue.location = user_extension_params["location"]
ue.location_city = user_extension_params["location_city"]
ue.identity = user_extension_params["identity"]
ue.technical_title = user_extension_params["technical_title"]
ue.student_id = user_extension_params["student_id"]
ue.description = user_extension_params["description"]
ue.save!
u.save!
sync_params = {}
if (user_params["mail"] && user_params["mail"] != user_mail)
sync_params = sync_params.merge(email: user_params["mail"])
end
if sync_params.present?
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
if interactor.success?
render_ok
else
render_error(interactor.error)
end
end
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(-1, e.message)
end
# 其他平台同步登录
def remote_login
@user = User.try_to_login(params[:login], params[:password])
if @user
successful_authentication(@user)
render_ok({user: {id: @user.id, token: @user.gitea_token}})
else
render_error("用户不存在")
end
end
#修改密码
def remote_password
@user = User.find_by(login: params[:login])
return render_error("未找到相关用户!") if @user.blank?
sync_params = {
password: params[:password].to_s,
email: @user.mail
}
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
if interactor.success?
@user.update_attribute(:password, params[:password])
render_ok
else
render_error(interactor.error)
end
end
# 用户注册
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
# params[:login] 邮箱或者手机号
# params[:code] 验证码
# code_type 1注册手机验证码 8邮箱注册验证码
# 本地forge注册入口
def register
begin
# 查询验证码是否正确;type只可能是1或者8
type = phone_mail_type(params[:login].strip)
code = params[:code].strip
# code = params[:code].strip
if type == 1
uid_logger("start register by phone: type is #{type}")
pre = 'p'
email = nil
phone = params[:login]
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
# verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
# TODO: 暂时限定邮箱注册
return normal_status(-1, '只支持邮箱注册')
else
uid_logger("start register by email: type is #{type}")
pre = 'm'
email = params[:login]
phone = nil
verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login])
return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL
# verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
end
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
# uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
# todo 上线前请删除万能验证码"513231"
unless code == "513231" && request.subdomain == "test-newweb"
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
end
return normal_status(-1, "8~16位密码支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
code = generate_identifier User, 8, pre
@ -78,23 +146,20 @@ class AccountsController < ApplicationController
# 现在因为是验证码,所以在注册的时候就可以激活
@user.activate
# 必须要用save操作密码的保存是在users中
if @user.save!
# todo user_extension
UserExtension.create!(user_id: @user.id)
# 注册完成手机号或邮箱想可以奖励500金币
# RewardGradeService.call(
# @user,
# container_id: @user.id,
# container_type: pre == 'p' ? 'Phone' : 'Mail',
# score: 500
# )
# 注册时,记录是否是引流用户
ip = request.remote_ip
ua = UserAgent.find_by_ip(ip)
ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua
successful_authentication(@user)
# session[:user_id] = @user.id
normal_status("注册成功")
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]})
if interactor.success?
gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
@user.gitea_token = result['sha1']
@user.gitea_uid = gitea_user['id']
if @user.save!
UserExtension.create!(user_id: @user.id)
successful_authentication(@user)
normal_status("注册成功")
end
else
tip_exception(-1, interactor.error)
end
rescue Exception => e
uid_logger_error(e.message)
@ -125,7 +190,7 @@ class AccountsController < ApplicationController
end
successful_authentication(@user)
login_control.clear # 重置每日密码错误次数
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
# session[:user_id] = @user.id
end
@ -171,27 +236,33 @@ class AccountsController < ApplicationController
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
user.update_column(:last_login_on, Time.now)
session[:"#{default_yun_session}"] = user.id
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
# 注册完成后有一天的试用申请(先去掉)
# UserDayCertification.create(user_id: user.id, status: 1)
end
# def set_autologin_cookie(user)
# token = Token.get_or_create_permanent_login_token(user, "autologin")
# cookie_options = {
# :value => token.value,
# :expires => 1.month.from_now,
# :path => '/',
# :secure => false,
# :httponly => true
# }
# if edu_setting('cookie_domain').present?
# cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
# end
# cookies[autologin_cookie_name] = cookie_options
# logger.info("cookies is #{cookies}")
# end
def set_autologin_cookie(user)
token = Token.get_or_create_permanent_login_token(user, "autologin")
sync_user_token_to_trustie(user.login, token.value)
cookie_options = {
:value => token.value,
:expires => 1.month.from_now,
:path => '/',
:secure => false,
:httponly => true
}
if edu_setting('cookie_domain').present?
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
end
cookies[autologin_cookie_name] = cookie_options
cookies.signed[:user_id] ||= user.id
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
end
def logout
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
logout_user
render :json => {status: 1, message: "退出成功!"}

View File

@ -14,6 +14,7 @@ class Admins::BaseController < ApplicationController
private
def require_login
# User.current = User.find 1
return if User.current.logged?
redirect_to "/login?back_url=#{CGI::escape(request.fullpath)}"
@ -42,4 +43,4 @@ class Admins::BaseController < ApplicationController
def setup_laboratory
Laboratory.current = Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1)
end
end
end

View File

@ -3,7 +3,13 @@ class Admins::LaboratoriesController < Admins::BaseController
default_sort('id', 'desc')
laboratories = Admins::LaboratoryQuery.call(params)
@laboratories = paginate laboratories.preload(:school, :laboratory_users)
@laboratories = paginate laboratories.preload(:laboratory_users)
end
def new
respond_to do |format|
format.js
end
end
def create
@ -82,4 +88,4 @@ class Admins::LaboratoriesController < Admins::BaseController
def setting_params
params.permit(:sync_course, :sync_subject, :sync_shixun)
end
end
end

View File

@ -1,4 +1,11 @@
class Admins::LaboratorySettingsController < Admins::BaseController
def new
respond_to do |format|
format.js
end
end
def show
@laboratory = current_laboratory
end

View File

@ -0,0 +1,83 @@
class Admins::ProjectCategoriesController < Admins::BaseController
before_action :get_category, only: [:edit,:update, :destroy]
before_action :validate_names, only: [:create, :update]
def index
sort_by = params[:sort_by] ||= 'created_at'
sort_direction = params[:sort_direction] ||= 'desc'
q = ProjectCategory.ransack(name_cont: params[:name])
project_categories = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@project_categories = paginate(project_categories)
end
def new
@project_category = ProjectCategory.new
end
def edit
end
def create
max_position_items = ProjectCategory.select(:id, :position).pluck(:position).reject!(&:blank?)
max_position = max_position_items.present? ? max_position_items.max.to_i : 0
@project_category = ProjectCategory.new(name: @name,position: max_position)
if @project_category.save
redirect_to admins_project_categories_path
flash[:success] = '创建成功'
else
redirect_to admins_project_categories_path
flash[:danger] = '创建失败'
end
end
def update
if @project_category.update_attribute(:name, @name)
redirect_to admins_project_categories_path
flash[:success] = '更新成功'
else
redirect_to admins_project_categories_path
flash[:success] = '更新失败'
end
end
def destroy
if @project_language.destroy
redirect_to admins_project_categories_path
flash[:success] = "删除成功"
else
redirect_to admins_project_categories_path
flash[:danger] = "删除失败"
end
end
private
def get_category
@project_category = ProjectCategory.find_by(id: params[:id])
unless @project_category.present?
redirect_to admins_project_categories_path
flash[:danger] = "分类不存在"
end
end
def check_language_present?(name)
return true if name.blank?
name_downcase = name.downcase
name_upcase = name.upcase
name_first_big = name.capitalize
ProjectCategory.exists?(name: name_downcase) || ProjectCategory.exists?(name: name_upcase) || ProjectCategory.exists?(name: name_first_big)
end
def validate_names
@name = params[:project_category][:name].to_s.first(64)
if @name.blank?
redirect_to admins_project_categories_path
flash[:danger] = '名称不能为空'
elsif check_language_present?(@name) && @project_category.blank?
redirect_to admins_project_categories_path
flash[:danger] = '分类已存在'
end
end
end

View File

@ -0,0 +1,120 @@
class Admins::ProjectIgnoresController < Admins::BaseController
before_action :set_ignore, only: [:edit,:update, :destroy,:show]
before_action :validate_params, only: [:create, :update]
def index
sort_by = params[:sort_by] ||= 'created_at'
sort_direction = params[:sort_direction] ||= 'desc'
q = Ignore.ransack(name_cont: params[:search])
project_ignores = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@project_ignores = paginate(project_ignores)
end
def new
@project_ignore = Ignore.new
end
def show
end
def create
# conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present?
# permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present?
# limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present?
# max_position_items = License.select(:id, :position).pluck(:position).reject!(&:blank?)
# max_position = max_position_items.present? ? max_position_items.max.to_i : 0
# other_params = {
# conditions: conditions.to_s,
# permissions: permissions.to_s,
# limitations: limitations.to_s,
# position: max_position
# }
@project_ignore = Ignore.new(ignore_params)
if @project_ignore.save!
redirect_to admins_project_ignores_path
flash[:success] = "创建成功"
else
render :new
flash[:danger] = "创建失败"
end
end
def edit
end
def update
# conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present?
# permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present?
# limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present?
# other_params = {
# conditions: conditions.to_s,
# permissions: permissions.to_s,
# limitations: limitations.to_s
# }
if @project_ignore.update_attributes(ignore_params)
redirect_to admins_project_ignores_path
flash[:success] = "更新成功"
else
render :edit
flash[:danger] = "更新失败"
end
end
def destroy
if @project_ignore.present?
if @project_ignore.destroy
redirect_to admins_project_ignores_path
flash[:success] = "删除成功"
else
redirect_to admins_project_ignores_path
flash[:success] = "删除失败"
end
else
redirect_to admins_project_ignores_path
flash[:success] = "删除失败:许可证已被项目引用"
end
end
# def move
# cate_opt = params[:opr]
# cate_position = @project_license.position.to_i
# move_status = up_and_down(cate_opt,@project_license,cate_position,"license")
# if move_status == 0
# @c_msg = "移动成功"
# else
# @c_msg = "移动失败"
# end
# end
private
def set_ignore
@project_ignore = Ignore.find_by_id(params[:id])
end
def ignore_params
params.require(:ignore).permit(:name,:content)
end
def validate_params
name = params[:ignore][:name]
if name.blank?
flash[:danger] = "名称不允许为空"
redirect_to admins_project_ignores_path
elsif check_ignore_present?(name) && @project_ignore.blank?
flash[:danger] = "创建失败:名称已存在"
redirect_to admins_project_ignores_path
end
end
def check_ignore_present?(name)
return true if name.blank?
name_downcase = name.downcase
name_upcase = name.upcase
name_first_big = name.capitalize
Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big)
end
end

View File

@ -0,0 +1,82 @@
class Admins::ProjectLanguagesController < Admins::BaseController
before_action :get_language, only: [:edit,:update, :destroy]
before_action :validate_names, only: [:create, :update]
def index
sort_by = params[:sort_by] ||= 'created_at'
sort_direction = params[:sort_direction] ||= 'desc'
q = ProjectLanguage.ransack(name_cont: params[:search])
project_languages = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@project_languages = paginate(project_languages)
end
def new
@project_language = ProjectLanguage.new
end
def edit
end
def create
max_position_items = ProjectLanguage.select(:id, :position).pluck(:position).reject!(&:blank?)
max_position = max_position_items.present? ? max_position_items.max.to_i : 0
@project_language = ProjectLanguage.new(name: @name,position:max_position)
if @project_language.save
redirect_to admins_project_languages_path
flash[:success] = '创建成功'
else
redirect_to admins_project_languages_path
flash[:danger] = '创建失败'
end
end
def update
if @project_language.update_attribute(:name, @name)
redirect_to admins_project_languages_path
flash[:success] = '更新成功'
else
redirect_to admins_project_languages_path
flash[:success] = '更新失败'
end
end
def destroy
if @project_language.destroy
redirect_to admins_project_languages_path
flash[:success] = "项目语言删除成功"
else
redirect_to admins_project_languages_path
flash[:danger] = "项目语言删除失败"
end
end
private
def get_language
@project_language = ProjectLanguage.find_by(id: params[:id])
unless @project_language.present?
redirect_to admins_project_languages_path
flash[:danger] = "项目语言不存在"
end
end
def check_language_present?(name)
return true if name.blank?
name_downcase = name.downcase
name_upcase = name.upcase
name_first_big = name.capitalize
ProjectLanguage.exists?(name: name_downcase) || ProjectLanguage.exists?(name: name_upcase) || ProjectLanguage.exists?(name: name_first_big)
end
def validate_names
@name = params[:project_language][:name].to_s.first(64)
if @name.blank?
redirect_to admins_project_languages_path
flash[:danger] = '名称不能为空'
elsif check_language_present?(@name) && @project_language.blank?
redirect_to admins_project_languages_path
flash[:danger] = '项目语言已存在'
end
end
end

View File

@ -0,0 +1,120 @@
class Admins::ProjectLicensesController < Admins::BaseController
before_action :set_license, only: [:edit,:update, :destroy,:show]
before_action :validate_params, only: [:create, :update]
def index
sort_by = params[:sort_by] ||= 'created_at'
sort_direction = params[:sort_direction] ||= 'desc'
q = License.ransack(name_cont: params[:search])
project_licenses = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
@project_licenses = paginate(project_licenses)
end
def new
@project_license = License.new
end
def show
end
def create
# conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present?
# permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present?
# limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present?
# max_position_items = License.select(:id, :position).pluck(:position).reject!(&:blank?)
# max_position = max_position_items.present? ? max_position_items.max.to_i : 0
# other_params = {
# conditions: conditions.to_s,
# permissions: permissions.to_s,
# limitations: limitations.to_s,
# position: max_position
# }
@project_license = License.new(license_params)
if @project_license.save!
redirect_to admins_project_licenses_path
flash[:success] = "创建成功"
else
render :new
flash[:danger] = "创建失败"
end
end
def edit
end
def update
# conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present?
# permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present?
# limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present?
# other_params = {
# conditions: conditions.to_s,
# permissions: permissions.to_s,
# limitations: limitations.to_s
# }
if @project_license.update_attributes(license_params)
redirect_to admins_project_licenses_path
flash[:success] = "更新成功"
else
render :edit
flash[:danger] = "更新失败"
end
end
def destroy
if @project_license.present?
if @project_license.destroy
redirect_to admins_project_licenses_path
flash[:success] = "删除成功"
else
redirect_to admins_project_licenses_path
flash[:success] = "删除失败"
end
else
redirect_to admins_project_licenses_path
flash[:success] = "删除失败:许可证已被项目引用"
end
end
# def move
# cate_opt = params[:opr]
# cate_position = @project_license.position.to_i
# move_status = up_and_down(cate_opt,@project_license,cate_position,"license")
# if move_status == 0
# @c_msg = "移动成功"
# else
# @c_msg = "移动失败"
# end
# end
private
def set_license
@project_license = License.find_by_id(params[:id])
end
def license_params
params.require(:license).permit(:name,:content)
end
def validate_params
name = params[:license][:name]
if name.blank?
flash[:danger] = "名称不允许为空"
redirect_to admins_project_licenses_path
elsif check_license_present?(name) && @project_license.blank?
flash[:danger] = "创建失败:名称已存在"
redirect_to admins_project_licenses_path
end
end
def check_license_present?(name)
return true if name.blank?
name_downcase = name.downcase
name_upcase = name.upcase
name_first_big = name.capitalize
License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big)
end
end

View File

@ -1,25 +1,25 @@
class Admins::ProjectsController < Admins::BaseController
def index
default_sort('created_at', 'desc')
sort_by = params[:sort_by] ||= 'created_on'
sort_direction = params[:sort_direction] ||= 'desc'
search = params[:search].to_s.strip
projects = Project.where("name like ?", "%#{search}%")
projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}")
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
end
def destroy
project = Project.find_by!(id: params[:id])
ActiveRecord::Base.transaction do
g = Gitlab.client
g.delete_project(project.gpid)
# 删除Trustie版本库记录
repoisitory = Repository.where(project_id: project.id, type: "Repository::Gitlab").first
repoisitory.destroy!
Tiding.where(container_id: project.id, container_type: ["JoinProject", "DealProject", "ReporterJoinProject", "ManagerJoinProject"]).destroy_all
Gitea::Repository::DeleteService.new(project.owner, project.identifier).call
project.destroy!
render_delete_success
# render_delete_success
redirect_to admins_projects_path
flash[:success] = "删除成功"
end
rescue Exception => e
redirect_to admins_projects_path
flash[:danger] = "删除失败"
end
end

View File

@ -4,7 +4,7 @@ class Admins::UsersController < Admins::BaseController
params[:sort_direction] = params[:sort_direction].presence || 'desc'
users = Admins::UserQuery.call(params)
@users = paginate users.includes(user_extension: :school)
@users = paginate users.includes(:user_extension, projects: :members)
end
def edit
@ -65,4 +65,4 @@ class Admins::UsersController < Admins::BaseController
mail phone location location_city school_id department_id admin business is_test
password professional_certification authentication])
end
end
end

View File

@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base
include GitHelper
include LoggerHelper
include LoginHelper
include RegisterHelper
protect_from_forgery prepend: true, unless: -> { request.format.json? }
@ -16,6 +17,14 @@ class ApplicationController < ActionController::Base
before_action :user_setup
#before_action :check_account
# TODO
# check sql query time
before_action do
if request.subdomain === 'testforgeplus' || request.subdomain === "profiler"
Rack::MiniProfiler.authorize_request
end
end
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"
@ -23,23 +32,23 @@ class ApplicationController < ActionController::Base
# 所有请求必须合法签名
def check_sign
if !Rails.env.development?
Rails.logger.info("66666 #{params}")
# suffix = request.url.split(".").last.split("?").first
# suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释
# unless suffix_arr.include?(suffix)
if params[:client_key].present?
randomcode = params[:randomcode]
# tip_exception(501, "请求不合理") unless (Time.now.to_i - randomcode.to_i).between?(0,5)
sign = Digest::MD5.hexdigest("#{OPENKEY}#{randomcode}")
Rails.logger.info("2222 #{sign}")
tip_exception(501, "请求不合理") if sign != params[:client_key]
else
tip_exception(501, "请求不合理")
end
# end
end
# if !Rails.env.development?
# Rails.logger.info("66666 #{params}")
# # suffix = request.url.split(".").last.split("?").first
# # suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释
# # unless suffix_arr.include?(suffix)
# if params[:client_key].present?
# randomcode = params[:randomcode]
# # tip_exception(501, "请求不合理") unless (Time.now.to_i - randomcode.to_i).between?(0,5)
#
# sign = Digest::MD5.hexdigest("#{OPENKEY}#{randomcode}")
# Rails.logger.info("2222 #{sign}")
# tip_exception(501, "请求不合理") if sign != params[:client_key]
# else
# tip_exception(501, "请求不合理")
# end
# # end
# end
end
# 全局配置参数
@ -233,6 +242,7 @@ class ApplicationController < ActionController::Base
# 未授权的捕捉407弹试用申请弹框
def require_login
#6.13 -hs
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
@ -333,7 +343,10 @@ class ApplicationController < ActionController::Base
elsif params[:debug] == 'student'
User.current = User.find 8686
elsif params[:debug] == 'admin'
User.current = User.find 1
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
user = User.find 36480
User.current = user
cookies.signed[:user_id] = user.id
end
end
# User.current = User.find 81403
@ -361,8 +374,8 @@ class ApplicationController < ActionController::Base
# auto-login feature starts a new session
user = nil
Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ")
user = User.try_to_autologin(cookies[autologin_cookie_name]) if session[:"#{default_yun_session}"]
start_user_session(user) if user
user = User.try_to_autologin(cookies[autologin_cookie_name])
# start_user_session(user) if user # TODO 解决sso退出不同步的问题
user
end
end
@ -659,7 +672,13 @@ class ApplicationController < ActionController::Base
end
end
def kaminari_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
end
def strf_time(time)
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
@ -681,7 +700,8 @@ class ApplicationController < ActionController::Base
def find_user_with_id
@user = User.find_by_id params[:user_id]
render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
# render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
render_error("未找到相关的用户") unless @user
end
def find_repository
@ -689,6 +709,10 @@ class ApplicationController < ActionController::Base
render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo
end
def find_repository_by_id
@repo = Repository.find params[:id]
end
def find_project
project_id = params[:project_id] ? params[:project_id] : params[:id]
project = Project.where(identifier: project_id)
@ -701,11 +725,6 @@ class ApplicationController < ActionController::Base
render_not_found("未找到’#{project}’相关的项目") unless @project
end
def find_project_with_identifier
@project = Project.find_by_identifier! params[:id]
render_not_found("未找到’#{params[:id]}’相关的项目") unless @project
end
def find_project_with_id
@project = Project.find(params[:project_id] || params[:id])
rescue Exception => e
@ -717,6 +736,32 @@ class ApplicationController < ActionController::Base
interactor.success? ? render_ok : render_error(interactor.error)
end
# projects
def load_project
namespace = params[:owner]
id = params[:repo] || params[:id]
@project, @owner = Project.find_with_namespace(namespace, id)
if @project and current_user.can_read_project?(@project)
logger.info "########### has project and can read project"
@project
elsif @project && current_user.is_a?(AnonymousUser)
logger.info "###########This is AnonymousUser"
@project = nil if !@project.is_public?
render_forbidden and return
else
logger.info "###########project not found"
@project = nil
render_not_found and return
end
@project
end
def load_repository
@repository ||= load_project&.repository
end
private
def object_not_found
uid_logger("Missing template or cant't find record, responding with 404")

View File

@ -2,7 +2,7 @@
#
# 文件上传
class AttachmentsController < ApplicationController
before_action :require_login, :check_auth, except: [:show]
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
before_action :find_file, only: %i[show destroy]
before_action :attachment_candown, only: [:show]
skip_before_action :check_sign, only: [:show, :create]
@ -28,11 +28,20 @@ class AttachmentsController < ApplicationController
update_downloads(@file)
end
def get_file
normal_status(-1, "参数缺失") if params[:download_url].blank?
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
response = Faraday.get(url)
filename = params[:download_url].to_s.split("/").pop()
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
end
def create
# 1. 本地存储
# 2. 上传到云
begin
upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
raise "未上传文件" unless upload_file
@ -98,6 +107,26 @@ class AttachmentsController < ApplicationController
end
end
# 附件为视频时,点击播放
def preview_attachment
attachment = Attachment.find_by(id: params[:id])
dir_path = "#{Rails.root}/public/preview"
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
if params[:status] == "preview"
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
else
normal_status(-1, "出现错误,请稍后重试")
end
else
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
normal_status(1, "操作成功")
else
normal_status(-1, "出现错误,请稍后重试")
end
end
end
private
def find_file
@file =
@ -177,31 +206,14 @@ class AttachmentsController < ApplicationController
candown = true
unless params[:type] == 'history'
if @file.container && current_user.logged?
# 课堂资源、作业、毕设相关资源的权限判断
if @file.container.is_a?(Course)
course = @file.container
candown = current_user.member_of_course?(course) || (course.is_public? && @file.publiced?)
elsif @file.container.is_a?(HomeworkCommon) || @file.container.is_a?(GraduationTask) || @file.container.is_a?(GraduationTopic)
course = @file.container&.course
candown = current_user.member_of_course?(course)
elsif @file.container.is_a?(StudentWork)
course = @file.container&.homework_common&.course
candown = current_user.member_of_course?(course)
elsif @file.container.is_a?(StudentWorksScore)
course = @file.container&.student_work&.homework_common&.course
candown = current_user.member_of_course?(course)
elsif @file.container.is_a?(GraduationWork)
course = @file.container&.graduation_task&.course
candown = current_user.member_of_course?(course)
elsif @file.container.is_a?(GraduationWorkScore)
course = @file.container&.graduation_work&.graduation_task&.course
candown = current_user.member_of_course?(course)
elsif @file.container.is_a?(Issue)
if @file.container.is_a?(Issue)
course = @file.container.project
candown = course.member?(current_user)
elsif @file.container.is_a?(Journal)
course = @file.container.issue.project
candown = course.member?(current_user)
else
course = nil
end
tip_exception(403, "您没有权限进入") if course.present? && !candown
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)

View File

@ -1,12 +0,0 @@
class BlobController < ApplicationController
def new
commit unless @repository.empty?
end
def create
create_commit(Files::CreateService, success_path: after_create_path,
failure_view: :new,
failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref))
end
end

View File

@ -1,342 +0,0 @@
class ChallengesController < ApplicationController
before_action :require_login, :check_auth, except: [:index]
before_action :find_shixun, only: [:new, :create, :index]
skip_before_action :verify_authenticity_token, only: [:create, :update, :create_choose_question, :crud_answer]
before_action :find_challenge, only: [:edit, :show, :update, :create_choose_question, :index_down, :index_up,
:edit_choose_question, :show_choose_question, :destroy_challenge_choose,
:update_choose_question, :destroy, :crud_answer, :answer]
# 关卡更新和操作的权限控制
before_action :update_allowed, except: [:index]
# 关卡访问的权限控制
before_action :shixun_access_allowed, only: [:index]
include ShixunsHelper
include ChallengesHelper
# 新建实践题
def new
@position = @shixun.challenges.count + 1
@st = params[:st].to_i
@task_pass_default = PlatformSample.find_by(samples_type: "taskPass").try(:contents)
end
# params
# challenge:{"subject": "标题", "task_pass": "过关任务",
# "diffculty": "关卡难度", "score": "关卡分数", "st": "关卡类型"} 关卡相关信息
# challenge_tag: 关卡标签
#
def create
ActiveRecord::Base.transaction do
begin
@challenge = Challenge.new(challenge_params)
@challenge.position = @shixun.challenges.count + 1
@challenge.shixun_id = @shixun.id
@challenge.user_id = current_user.id
@challenge.modify_time = Time.now
@challenge.save!
# 实训是否需要重置, 非实践任务创建第一个阶段调用, 避免不包含实践任务的实训进行模拟实战报错 todo: 新建实训需要重置TPI
# shixun_modify_status_without_publish(@shixun, 1) if @challenge.position != 1
tags = params[:challenge_tag]
if tags.present?
tags.each do |tag|
# TODO 创建tag的时候为什么一直报challenge choose必须存在??
ChallengeTag.create!(name: tag, challenge_id: @challenge.id)
end
end
rescue Exception => e
uid_logger_error("create challenge failed #{e}")
end
end
end
# 创建选择题
def create_choose_question
ActiveRecord::Base.transaction do
begin
@challenge_choose = ChallengeChoose.new(chooce_params)
@challenge_choose.position = @challenge.challenge_chooses.count + 1
@challenge_choose.category = @challenge_choose.standard_answer.length == 1 ? 1 : 2
@challenge_choose.challenge_id = @challenge.id
if @challenge_choose.save!
# 创建选项
params[:question][:cnt].each_with_index do |test, index|
answer = params[:choice][:answer][index]
ChallengeQuestion.create(:option_name => test,
:challenge_choose_id => @challenge_choose.id,
:position => index, :right_key => answer)
end
# 创建单选多选的技能标签
if params[:challenge_tag].present?
params[:challenge_tag].each do |tag|
ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id)
end
end
@challenge.update_column(:score, @challenge.challenge_chooses.sum(:score))
end
rescue Exception => e
raise ActiveRecord::Rollback
end
end
end
# 选择题详情页面
def show_choose_question
@challenge_choose = ChallengeChoose.find params[:choose_id]
end
# 选择题更新页面
def update_choose_question
@challenge_choose = ChallengeChoose.find(params[:choose_id])
ActiveRecord::Base.transaction do
if params[:standard_answer] != @challenge_choose.standard_answer
@challenge.update_column(:modify_time, Time.now)
end
@challenge_choose.update_attributes(chooce_params)
@challenge.update_column(:score, @challenge.challenge_chooses.sum(:score))
# 单选多选题的更新
category = @challenge_choose.standard_answer.length > 1 ? 2 : 1
@challenge_choose.update_column(:category, category)
begin
@challenge_choose.challenge_questions.delete_all
params[:question][:cnt].each_with_index do |test, index|
answer = params[:choice][:answer][index]
ChallengeQuestion.create(:option_name => test, :challenge_choose_id => @challenge_choose.id, :position => index, :right_key => answer)
end
@challenge_choose.challenge_tags.delete_all unless @challenge_choose.challenge_tags.blank?
if params[:challenge_tag].present?
params[:challenge_tag].each do |tag|
ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id)
end
end
@challenge_choose = ChallengeChoose.find params[:choose_id]
rescue Exception => e
raise ActiveRecord::Rollback
end
end
end
# 选择题的编辑
def edit_choose_question
@challenge_choose = ChallengeChoose.find params[:choose_id]
end
def destroy_challenge_choose
ActiveRecord::Base.transaction do
@challenge_choose = ChallengeChoose.where(:id => params[:choose_id]).first
pos = @challenge_choose.position
@challenge.challenge_chooses.where("position > ?", pos).update_all("position = position - 1")
@challenge_choose.destroy
@status = 1
# 发起重置请求 TODO: 重置实训需要后续做
# shixun_modify_status_without_publish(@shixun, 1)
end
end
# 编辑模式
# tab 0,nil 过关任务, 1 评测设置, 2 参考答案
def edit
@tab = params[:tab].to_i
@power = @shixun.status == 0
challenge_num = Challenge.where(:shixun_id => @shixun).count
@position = @challenge.position
@chooses = @challenge.challenge_chooses
if @position < challenge_num
@next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first
end
@prev_challenge = Challenge.where(:shixun_id => @shixun, :position => @position - 1).first if @position - 1 > 0
end
def index
uid_logger("identifier: #{params}")
@challenges = @shixun.challenges.fields_for_list
@editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@user = current_user
@shixun.increment!(:visits)
end
def show
@tab = params[:tab].nil? ? 1 : params[:tab].to_i
challenge_num = @shixun.challenges_count
@power = @shixun.status == 0 # 之前验证走过了是不是管理员,因此这里只用判断是否发布
@position = @challenge.position
if @position < challenge_num
@next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first
end
@prev_challenge = Challenge.where(:shixun_id => @shixun, :position => @position - 1).first if @position - 1 > 0
end
# tab 0:过关任务的更新; 1:评测设置的更新; 2:表示参考答案的更新;
def update
begin
ActiveRecord::Base.transaction do
tab = params[:tab].to_i
@challenge.update_attributes!(challenge_params)
if tab == 0 && @challenge.st == 0
@challenge.challenge_tags.delete_all
if params[:challenge_tag].present?
params[:challenge_tag].each do |input|
ChallengeTag.create!(:name => input, :challenge_id => @challenge.id)
end
end
elsif tab == 1
path = @challenge.path
exec_path = @challenge.exec_path
test_set = @challenge.test_sets
sets_output = test_set.map(&:output)
sets_input = test_set.map(&:input)
sets_open = test_set.map(&:is_public)
set_score = test_set.map(&:score)
set_match_rule = test_set.map(&:match_rule)
params_hidden = params[:test_set].map{|set| set[:hidden].to_i == 0}
params_output = params[:test_set].map{|set| set[:output] }
params_input = params[:test_set].map{|set| set[:input] }
params_score = params[:test_set].map{|set| set[:score]}
params_test_set = params[:test_set].map{|set| set[:match_rule]}
# 测试集变化则需要更新(输入、 输出、 是否隐藏)
if sets_output != params_output || sets_open != params_hidden || sets_input != params_input ||
set_score != params_score || params_test_set != set_match_rule
test_set.delete_all unless test_set.blank?
params[:test_set].each_with_index do |set, index|
# last 末尾匹配, full: 全完匹配
logger.info("set: #{set}; match_rule : #{set[:match_rule]}")
match_rule = set[:match_rule] == 'last' ? 'last' : 'full'
TestSet.create!(:challenge_id => @challenge.id,
:input => "#{set[:input]}",
:output => "#{set[:output]}",
:is_public => params_hidden[index],
:score => set[:score],
:match_rule => "#{match_rule}",
:position => (index + 1))
end
@challenge.update_column(:modify_time, Time.now)
# 测试集的
@shixun.myshixuns.update_all(:system_tip => 0)
end
if params[:challenge][:show_type].to_i == -1
@challenge.update_attributes(picture_path: nil, web_route: nil, expect_picture_path: nil, original_picture_path: nil)
end
# 关卡评测执行文件如果被修改,需要修改脚本内容
logger.info("############shixun_publiced:#{@shixun.public == 0}")
if @shixun.public == 0
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
# TODO:
# if path != params[:challenge][:path]
# shixun_modify_status_without_publish(@shixun, 1)
# end
#Attachment.attach_files(@challenge, params[:attachments])
end
end
rescue Exception => e
logger.error("##update_challenges: ##{e.message}")
tip_exception("#{e.message}")
end
end
# 参考答案的'增,删,改'
# POST: /shixuns/:id/challenges/:id/crud_answer
# {'challenge_answer': [
# {'name': 'name', contents: 'contents', score: 10},
# {...},
# {...}, ...]
#}
def crud_answer
if @challenge.challenge_answers && params[:challenge_answer].blank?
@challenge.challenge_answers.destroy_all
else
raise '参考答案不能为空' if params[:challenge_answer].empty?
raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100
ActiveRecord::Base.transaction do
@challenge.challenge_answers.destroy_all if @challenge.challenge_answers
params[:challenge_answer].each_with_index do |answer, index|
# 内容为空不保存
next if answer[:contents].blank?
ChallengeAnswer.create!(name: answer[:name], contents: answer[:contents],
level: index+1, score: answer[:score], challenge_id: @challenge.id)
end
end
end
end
# 查看参考答案接口
def answer
@answers = @challenge.challenge_answers
end
def index_down
next_challenge = @challenge.next_challenge
position = @challenge.position
@challenge.update_attribute(:position, (position + 1))
next_challenge.update_attribute(:position, next_challenge.position - 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
def index_up
position = @challenge.position
last_challenge = @challenge.last_challenge
@challenge.update_attribute(:position, (position - 1))
last_challenge.update_attribute(:position, last_challenge.position + 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
def destroy
next_challenges = @shixun.challenges.where("position > #{@challenge.position}")
next_challenges.update_all("position = position - 1")
# Todo: 实训修改后,关卡需要重置
# shixun_modify_status_without_publish(@shixun, 1)
@challenge.destroy
# 关卡位置被删除,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.shixun_info.update_column(:evaluate_script, script)
end
private
def find_shixun
@shixun = Shixun.find_by_identifier(params[:shixun_identifier])
end
# 通用接口
def find_challenge
@challenge = Challenge.find params[:id]
@shixun = Shixun.find_by!(identifier: params[:shixun_identifier])
end
def challenge_params
tip_exception("评测时间不能超过300秒") if params[:challenge][:exec_time].to_i > 300
params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average,
:path, :exec_path, :show_type, :original_picture_path, :test_set_score,
:expect_picture_path, :picture_path, :web_route, :answer, :exec_time)
end
def chooce_params
params.require(:challenge_choose).permit(:subject, :answer,
:standard_answer, :score, :difficult)
end
def update_allowed
unless current_user.manager_of_shixun?(@shixun)
raise Educoder::TipException.new(403, "..")
end
end
end

View File

@ -0,0 +1,47 @@
class Ci::BaseController < ApplicationController
include Ci::DbConnectable
before_action :require_login
before_action :connect_to_ci_database, if: -> { current_user && !current_user.is_a?(AnonymousUser) && !current_user.devops_uninit? }
def load_repo
namespace = params[:owner]
id = params[:repo] || params[:id]
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
end
private
def authorize_access_project!
unless @project.manager?(current_user)
return render_forbidden
end
end
def authenticate_manager!
unless @project.manager?(current_user)
return render_forbidden
end
end
def authenticate_admin!
return render_forbidden unless current_user.admin?
end
def authorize_owner!
unless @project.owner?(current_user)
return render_forbidden
end
end
def find_cloud_account
@cloud_account ||= current_user.ci_cloud_account
@cloud_account.blank? ? nil : @cloud_account
end
def load_ci_user
@ci_user ||= Ci::User.find_by(user_login: params[:owner])
@ci_user.blank? ? raise("未找到相关的记录") : @ci_user
end
end

View File

@ -0,0 +1,54 @@
class Ci::BuildsController < Ci::BaseController
include RepositoriesHelper
before_action :load_project
before_action :authorize_owner!, only: [:restart, :stop]
before_action :load_repo
before_action :find_cloud_account, except: [:index, :show]
def index
@user = current_user
scope = @repo.builds
scope = Ci::Builds::ListQuery.call(@repo, params)
@total_count = scope.map(&:build_id).size
@builds = paginate scope
end
def show
@build = @repo.builds.includes(stages: [:steps]).find_by(build_number: params[:build])
end
def restart
result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).restart
render json: result
end
def stop
result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).stop
render json: result
end
def logs
# TODO **待优化**
# 因直接操作ci库如下查询待优化可直接根据log id查询即可
build = @repo.builds.find_by(build_number: params[:build])
return render_not_found("Couldn't found build with 'number'= #{params[:build]}") if build.blank?
stage = build.stages.includes(steps: [:log]).find_by(stage_number: params[:stage])
return render_not_found("Couldn't found build with 'number'= #{params[:stage]}") if stage.blank?
step = stage.steps.find_by(step_number: params[:step])
return render_not_found("Couldn't found build with 'number'= #{params[:step]}") if step.blank?
log = step.log
result = log.blank? ? nil : (log.log_data[0..5].include?('null') ? nil : JSON.parse(log.log_data))
# result = Ci::Drone::API.new(@user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, build: params[:build], stage: params[:stage], step: params[:step]).logs
render json: result
end
end

View File

@ -0,0 +1,101 @@
class Ci::CloudAccountsController < Ci::BaseController
include Ci::CloudAccountManageable
skip_before_action :connect_to_ci_database, only: %i[create bind]
before_action :load_project, only: %i[create activate]
before_action :authorize_owner!, only: %i[create activate]
before_action :load_repo, only: %i[activate]
before_action :find_cloud_account, only: %i[show oauth_grant]
before_action :validate_params!, only: %i[create bind]
before_action only: %i[create bind] do
connect_to_ci_database(master_db: true)
end
def create
flag, msg = check_bind_cloud_account!
return render_error(msg) if flag === true
ActiveRecord::Base.transaction do
@cloud_account = bind_account!
if @cloud_account.blank?
render_error('激活失败, 请检查你的云服务器信息是否正确.')
raise ActiveRecord::Rollback
else
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
render_ok(redirect_url: @cloud_account.authenticate_url)
end
end
rescue Exception => ex
render_error(ex.message)
end
def activate
return render_error('请先认证') unless current_user.ci_certification?
begin
@cloud_account = Ci::CloudAccount.find params[:id]
ActiveRecord::Base.transaction do
if @repo
return render_error('该项目已经激活') if @repo.repo_active?
@repo.activate!(@ci_user.user_id)
else
@repo = Ci::Repo.auto_create!(@ci_user, @project)
@user.update_column(:user_syncing, false)
end
result = bind_hook!(current_user, @cloud_account, @repo)
@project.update_columns(open_devops: true, gitea_webhook_id: result['id'])
@cloud_account.update_column(:ci_user_id, @ci_user.user_id)
end
render_ok
rescue Exception => ex
render_error(ex.message)
end
end
def show
end
def bind
flag, msg = check_bind_cloud_account!
return render_error(msg) if flag === true
ActiveRecord::Base.transaction do
@cloud_account = bind_account!
if @cloud_account.blank?
render_error('激活失败, 请检查你的云服务器信息是否正确.')
raise ActiveRecord::Rollback
else
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
end
end
rescue Exception => ex
render_error(ex.message)
end
def unbind
ActiveRecord::Base.transaction do
unbind_account!
render_ok
end
rescue Exception => ex
render_error(ex.message)
end
def oauth_grant
password = params[:password].to_s
return render_error('你输入的密码不正确.') unless current_user.check_password?(password)
oauth = current_user.oauths.last
return render_error("服务器出小差了.") if oauth.blank?
result = gitea_oauth_grant!(password, oauth)
return render_error('授权失败.') unless result === true
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
end
private
def validate_params!
Ci::CreateCloudAccountForm.new(devops_params).validate!
end
end

View File

@ -0,0 +1,20 @@
class Ci::LanguagesController < Ci::BaseController
# TODO 需要开启权限认证只有该项目devops初始化成功后才能获取语言列表
before_action :find_langugae, only: :show
def index
@languages = Ci::Language.by_usage_amount_desc
end
def show
end
def common
@languages = Ci::Language.six_common
end
private
def find_langugae
@language = Ci::Language.find params[:id]
end
end

View File

@ -0,0 +1,73 @@
class Ci::ProjectsController < Ci::BaseController
include RepositoriesHelper
include Ci::CloudAccountManageable
before_action :load_project
before_action :load_repo, only: [:update_trustie_pipeline, :activate, :deactivate]
before_action :authorize_owner!, only: [:authorize]
before_action :find_cloud_account, only: [:authorize, :activate, :deactivate]
def authorize
@user = current_user
end
# get .trustie-pipeline.yml file
def get_trustie_pipeline
file_path_uri = URI.parse('.trustie-pipeline.yml')
interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master")
if interactor.success?
file = interactor.result
return render json: {} if file[:status]
json = {name: file['name'], path: file['path'], sha: file['sha'], content: render_decode64_content(file['content'])}
render json: json
end
end
def update_trustie_pipeline
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, params[:owner], params.merge(identifier: @project.identifier))
if interactor.success?
@file = interactor.result
render_result(1, "更新成功")
else
render_error(interactor.error)
end
end
def activate
return render_error('你还未认证') unless current_user.ci_certification?
begin
ActiveRecord::Base.transaction do
if @repo
return render_error('该项目已经激活') if @repo.repo_active?
if @project.ci_reactivate?
@project.ci_reactivate!(@repo)
return render_ok
end
@repo.activate!(@ci_user.user_id)
else
@repo = Ci::Repo.auto_create!(@ci_user, @project)
@ci_user.update_column(:user_syncing, false)
end
result = bind_hook!(current_user, @cloud_account, @repo)
@project.update_columns(open_devops: true, gitea_webhook_id: result['id'])
@project.increment!(:open_devops_count)
@cloud_account.update_column(:ci_user_id, @ci_user.user_id)
end
render_ok
rescue Exception => ex
render_error(ex.message)
end
end
def deactivate
return render_error('该项目已经取消激活') if !@repo.repo_active?
@project.update_column(:open_devops, false)
@repo.deactivate!
render_ok
end
end

View File

@ -1,75 +0,0 @@
class CommentsController < ApplicationController
before_action :find_hack
before_action :require_login
# 评论
def create
begin
@discuss = @hack.discusses.new(comment_params) # 管理员回复的能够显示
@discuss.hidden = false
@discuss.user_id = current_user.id
@discuss.save!
rescue Exception => e
uid_logger_error("create discuss failed : #{e.message}")
render_error("评论异常")
end
end
# 回复
def reply
begin
@discuss = @hack.discusses.new(reply_params)
@discuss.hidden = false
@discuss.user_id = current_user.id
@discuss.root_id = params[:comments][:parent_id]
@discuss.save!
rescue Exception => e
uid_logger_error("reply discuss failed : #{e.message}")
render_error("回复评论异常")
end
end
# 列表
def index
discusses =
if current_user.admin_or_business?
@hack.discusses.where(root_id: nil)
else
@hack.discusses.where(root_id: nil, hidden: false)
end
@discusses_count = discusses.count
@discusses= paginate discusses
end
# 删除
def destroy
@hack.discusses.find_by(id: params[:id]).destroy
render_ok
end
# 隐藏、取消隐藏
def hidden
if current_user.admin_or_business?
@discuss = @hack.discusses.where(id: params[:id]).first
@discuss.update_attribute(:hidden, params[:hidden].to_i == 1)
sucess_status
else
Educoder::TipException(403, "..")
end
end
private
def find_hack
@hack = Hack.find_by_identifier(params[:hack_identifier])
end
def comment_params
params.require(:comments).permit(:content)
end
def reply_params
params.require(:comments).permit(:content, :parent_id)
end
end

View File

@ -0,0 +1,15 @@
class CompareController < ApplicationController
# skip_before_action :require_login
before_action :load_repository
def index
end
def show
base_ref = Addressable::URI.unescape(params[:base])
@ref = head_ref = Addressable::URI.unescape(params[:head]&.split('.json')[0])
@compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base_ref, head_ref)
# render json: @compare_result
end
end

View File

@ -0,0 +1,138 @@
module Ci::CloudAccountManageable
extend ActiveSupport::Concern
included do
end
def bind_account!
# 1. 保存华为云服务器帐号
create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num].strip).to_i, secret: Ci::CloudAccount.encrypted_secret(devops_params[:secret]))
cloud_account = Ci::CloudAccount.new(create_params)
cloud_account.user = current_user
cloud_account.save!
# 2. 生成oauth2应用程序的client_id和client_secrete
gitea_oauth = Gitea::Oauth2::CreateService.call(current_user.gitea_token, {name: "pipeline-#{SecureRandom.hex(8)}", redirect_uris: ["#{cloud_account.drone_url}/login"]})
logger.info "######### gitea_oauth: #{gitea_oauth}"
oauth = Oauth.new(client_id: gitea_oauth['client_id'],
client_secret: gitea_oauth['client_secret'],
redirect_uri: gitea_oauth['redirect_uris'],
gitea_oauth_id: gitea_oauth['id'],
user_id: current_user.id)
oauth.save!
# 创建数据ci端数据库
database_result = auto_create_database!(@connection, "#{current_user.login}_drone")
logger.info "[CI::DbConnectable] auto_create_database's result: #{database_result}"
# 初始化表结构
sub_connection = connect_to_ci_database
auto_create_table_structure!(sub_connection)
rpc_secret = SecureRandom.hex 16
logger.info "######### rpc_secret: #{rpc_secret}"
# 3. 创建drone server
drone_server_cmd = Ci::Drone::Server.new(current_user.login, oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd
logger.info "######### drone_server_cmd: #{drone_server_cmd}"
# 4. 创建drone client
drone_client_cmd = Ci::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd
logger.info "######### drone_client_cmd: #{drone_client_cmd}"
# 5. 登录远程服务器启动drone服务
result = Ci::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run
logger.info "######### result: #{result}"
redirect_url = "#{cloud_account.drone_url}/login"
logger.info "######### redirect_url: #{redirect_url}"
return nil unless result.present?
result && !result.blank? ? cloud_account : nil
end
def unbind_account!
cloud_account = current_user.ci_cloud_account
return render_error('你未绑定CI服务器') if current_user.devops_step == User::DEVOPS_UNINIT || cloud_account.blank?
cloud_account.destroy! unless cloud_account.blank?
@connection.execute("DROP DATABASE IF EXISTS #{current_user.login}_drone") # TOTO drop drone database
current_user.unbind_account!
end
def bind_hook!(user, cloud_account, repo)
hook_params = {
active: true,
config: {
content_type: "json",
url: cloud_account.drone_url + "/hook?secret=#{repo.repo_signer}"
},
type: "gitea"
}
result = Gitea::Hooks::CreateService.call(user.gitea_token, user.login, repo.repo_name, hook_params)
result[:status].present? ? nil : result
end
def check_bind_cloud_account!
return [true, "你已经绑定了云帐号."] unless current_user.ci_cloud_account.blank?
ip_num = IPAddr.new(devops_params[:ip_num]).to_i
Ci::CloudAccount.exists?(ip_num: ip_num) ? [true, "#{devops_params[:ip_num]}服务器已被使用."] : [false, nil]
end
def gitea_auto_create_auth_grant!(gitea_oauth_id)
connection = Gitea::Database.set_connection.connection
unix_time = Time.now.to_i
# 目前直接操作db可以建立对应的model进行操作
sql = "INSERT INTO oauth2_grant ( user_id, application_id, counter, created_unix, updated_unix ) VALUES ( #{current_user.gitea_uid}, #{gitea_oauth_id}, 0, #{unix_time}, #{unix_time} );"
connection.execute(sql)
end
def gitea_oauth_grant!(password, oauth)
gitea_auto_create_auth_grant!(oauth&.gitea_oauth_id)
state = SecureRandom.hex(8)
# redirect_uri eg:
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{oauth&.client_id}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}"
logger.info "[gitea] grant_url: #{grant_url}"
conn = Faraday.new(url: grant_url) do |req|
req.request :url_encoded
req.adapter Faraday.default_adapter
req.basic_auth(current_user.login, password)
end
response = conn.get
logger.info "[gitea] response headers: #{response.headers}"
drone_oauth_user!(response.headers.to_h['location'], state)
end
def drone_oauth_user!(url, state)
logger.info "[drone] drone_oauth_user url: #{url}"
conn = Faraday.new(url: url) do |req|
req.request :url_encoded
req.adapter Faraday.default_adapter
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
end
response = conn.get
logger.info "[drone] response headers: #{response.headers}"
response.headers['location'].include?('error') ? false : true
end
private
def devops_params
params.permit(:account, :secret, :ip_num)
end
end

View File

@ -0,0 +1,40 @@
module Ci::DbConnectable
extend ActiveSupport::Concern
include do
end
# Dynamically sets the database connection.
def connect_to_ci_database(options={})
master_db = options[:master_db] || false
config = Rails.application.config_for(:configuration).symbolize_keys!
db_config = config[:ci_db_server].symbolize_keys!
raise 'ci database config missing' if db_config.blank?
req_params = {
host: db_config[:host],
username: db_config[:username],
password: db_config[:password],
port: db_config[:port]
}
req_params = req_params.merge(database: "#{current_user.login}_#{db_config[:database]}") unless master_db === true
db_params = Ci::Database.get_connection_params(req_params)
@connection = Ci::Database.set_connection(db_params).connection
end
def auto_create_database!(connection, database)
Rails.logger.info "[CI::DbConnectable] auto_create_database's connection: #{connection}"
connection.execute("CREATE DATABASE IF NOT EXISTS #{database}")
end
def auto_create_table_structure!(connection)
Rails.logger.info "[CI::DbConnectable] auto_create_table_structure's connection: #{connection}"
sqls = Ci::Schema.statement.split(';').map(&:strip).reject { |e| e.to_s.empty? }
sqls.each do |sql|
con_result = connection.execute(sql)
Rails.logger.info "=============> ci create tabels result: #{con_result}"
end
end
end

View File

@ -7,6 +7,7 @@ module LaboratoryHelper
helper_method :current_laboratory
helper_method :default_setting
helper_method :default_yun_session
helper_method :default_course_links
end
def current_laboratory
@ -29,4 +30,20 @@ module LaboratoryHelper
laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1))
@_default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id"
end
end
def default_course_links
# my_projects: "/users/#{current_user.try(:login)}/projects",
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
{
new_syllabuses: "https://www.trustie.net/syllabuses/new",
new_course: "https://www.trustie.net/courses/new",
edit_account: "https://www.trustie.net/my/account",
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
my_projects: "/users/#{current_user.try(:login)}/projects",
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
default_url: "https://www.trustie.net/",
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
register_url: "https://www.trustie.net/login?login=false"
}
end
end

View File

@ -11,18 +11,28 @@ module LoginHelper
def set_autologin_cookie(user)
token = Token.get_or_create_permanent_login_token(user, "autologin")
sync_user_token_to_trustie(user.login, token.value)
Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
cookie_options = {
:value => token.value,
:expires => 1.month.from_now,
:path => '/',
:secure => false,
:httponly => false
:httponly => true
}
if edu_setting('cookie_domain').present?
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
end
# unless cookies[autologin_cookie_name].present?
# cookies[autologin_cookie_name] = cookie_options
# end
cookies[autologin_cookie_name] = cookie_options
Rails.logger.info("cookies is #{cookies}")
# for action cable
cookies.signed[:user_id] ||= user.id
Rails.logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]}")
end
def successful_authentication(user)
@ -40,13 +50,22 @@ module LoginHelper
end
def logout_user
Rails.logger.info("####################__User.current_id______######{current_user.try(:id)}###___#{current_user&.logged?}")
if User.current.logged?
if autologin = cookies.delete(autologin_cookie_name)
User.current.delete_autologin_token(autologin)
end
User.current.delete_session_token(session[:tk])
user = User.current
autologin =
if edu_setting('cookie_domain').present?
cookies.delete(autologin_cookie_name, domain: edu_setting('cookie_domain'))
else
cookies.delete(autologin_cookie_name)
end
user.delete_autologin_token(autologin)
user.delete_session_token(session[:tk])
self.logged_user = nil
end
# 云上实验室退出清理当前session
laboratory ||= (Laboratory.find_by_subdomain(request.subdomain) || Laboratory.find(1))
default_yun_session = "#{laboratory.try(:identifier).split('.').first}_user_id"
@ -56,8 +75,10 @@ module LoginHelper
# Sets the logged in user
def logged_user=(user)
# reset_session
reset_session
if user && user.is_a?(User)
Rails.logger.info("########________logged_user___________###########{user.id}")
User.current = user
start_user_session(user)
else
@ -78,8 +99,53 @@ module LoginHelper
# # end
# session[:user_id] = user.id
Rails.logger.info("########________start_user_session___________###########{user.id}")
session[:"#{default_yun_session}"] = user.id
session[:ctime] = Time.now.utc.to_i
session[:atime] = Time.now.utc.to_i
end
end
def sync_pwd_to_gitea!(user, hash={})
return true if user.is_sync_pwd?
sync_params = { email: user.mail }
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
if interactor.success?
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
true
else
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"
false
end
end
# TODO 同步token到trustie平台保持同步登录状态
def sync_user_token_to_trustie(login, token_value)
config = Rails.application.config_for(:configuration).symbolize_keys!
token = config[:sync_token]
api_host = config[:sync_url]
return if api_host.blank?
url = "#{api_host}/api/v1/users/sync_user_token"
sync_json = {
"token": token,
"login": login,
"user_token": token_value
}
uri = URI.parse(url)
if api_host
http = Net::HTTP.new(uri.hostname, uri.port)
if api_host.include?("https://")
http.use_ssl = true
end
http.send_request('POST', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'})
end
end
end

View File

@ -5,7 +5,12 @@ module OperateProjectAbilityAble
end
def authorizate_user_can_edit_project!
return if current_user.project_manager? @project || current_user.admin?
return if @project.manager?(current_user) || current_user.admin?
render_forbidden('你没有权限操作.')
end
def authorizate_user_can_edit_repo!
return if @repository.project.manager?(current_user) || current_user.admin?
render_forbidden('你没有权限操作.')
end

View File

@ -0,0 +1,28 @@
module RegisterHelper
extend ActiveSupport::Concern
def autologin_register(username, email, password, platform= 'forge')
result = {message: nil, user: nil}
user = User.new(admin: false, login: username, mail: email, type: "User")
user.password = password
user.platform = platform
user.activate
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
if interactor.success?
gitea_user = interactor.result
result = Gitea::User::GenerateTokenService.new(username, password).call
user.gitea_token = result['sha1']
user.gitea_uid = gitea_user['id']
if user.save!
UserExtension.create!(user_id: user.id)
result[:user] = {id: user.id, token: user.gitea_token}
end
else
result[:message] = interactor.error
end
result
end
end

View File

@ -1,73 +0,0 @@
class CourseGroupsController < ApplicationController
before_action :require_login, :check_auth
before_action :set_group, except: [:create]
before_action :find_course, only: [:create]
before_action :teacher_allowed, except: [:set_invite_code_halt]
def create
tip_exception("分班名称不能为空") if params[:name].blank?
if @course.course_groups.where(name: params[:name]).count > 0
normal_status(-1, "已存在同名分班")
else
course_group = @course.course_groups.create!(name: params[:name], position: @course.course_groups.count + 1)
render :json => {group_id: course_group.id, status: 0, message: "创建成功"}
end
end
def destroy
ActiveRecord::Base.transaction do
begin
@course.course_groups.where("position > #{@group.position}").update_all("position = position - 1")
# 将该分班的学生转到未分班
@group.course_members.update_all(course_group_id: 0)
@group.destroy
rescue Exception => e
uid_logger_error(e.message)
tip_exception("删除分班失败")
end
end
end
# 分班重命名
def rename_group
tip_exception("名称不能为空") if params[:name].blank?
if @course.course_groups.where(name: params[:name]).count > 0
normal_status(-1, "已存在同名分班")
else
@group.update_attributes(name: params[:name].strip)
normal_status(0, "更新成功")
end
end
# 分班的拖动
def move_category
tip_exception("移动失败") if params[:position].blank?
unless params[:position].to_i == @group.position
if params[:position].to_i < @group.position
@course.course_groups.where("position < #{@group.position} and position >= ?", params[:position]).update_all("position = position + 1")
else
@course.course_groups.where("position > #{@group.position} and position <= ?", params[:position]).update_all("position = position - 1")
end
@group.update_attributes(position: params[:position])
normal_status(0, "移动成功")
else
normal_status(-1, "位置没有变化")
end
end
# 邀请码停用/启用
def set_invite_code_halt
teacher = @course.teachers.find_by(user_id: current_user.id)
tip_exception(403, "无权限") unless current_user.admin_or_business? ||
(teacher.present? && (teacher.teacher_course_groups.pluck(:course_group_id).include?(@group.id) || teacher.teacher_course_groups.size == 0))
@group.update!(invite_code_halt: !@group.invite_code_halt)
normal_status(0, "成功")
end
private
def set_group
@group = CourseGroup.find_by!(id: params[:id])
@course = @group.course
end
end

View File

@ -1,68 +0,0 @@
class CourseModulesController < ApplicationController
before_action :require_login, :check_auth
before_action :set_module, except: [:unhidden_modules]
before_action :find_course, only: [:unhidden_modules]
before_action :teacher_or_admin_allowed, except: [:add_second_category]
before_action :teacher_allowed, only: [:add_second_category]
# 模块置顶
def sticky_module
# position为1则不做处理否则该模块的position置为1position小于当前模块的position加1
unless @course_module.position == 1
@course.course_modules.where("position < #{@course_module.position}").update_all("position = position + 1")
@course_module.update_attributes(position: 1)
end
normal_status(0, "置顶成功")
end
# 模块隐藏
def hidden_module
tip_exception("请至少保留一个课堂模块") if @course.none_hidden_course_modules.where.not(id: @course_module.id).size == 0
@course_module.update_attributes(hidden: 1)
normal_status(0, "更新成功")
end
# 模块重命名
def rename_module
name = params[:name].strip
tip_exception("名称不能为空") if name.blank?
tip_exception("已存在同名模块") if @course.course_modules.exists?(module_name: name)
@course_module.update_attributes(module_name: name)
case @course_module.module_type
when 'board'
@course.course_board.update_columns(name: name)
end
normal_status(0, "更新成功")
end
# 模块的显示
def unhidden_modules
tip_exception("请选择要显示的模块") if params[:module_ids].blank?
@course.course_modules.where(id: params[:module_ids]).update_all(hidden: 0)
normal_status(0, "更新成功")
end
# 添加二级目录
def add_second_category
tip_exception("子目录名称不能为空") if params[:name].blank?
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
ActiveRecord::Base.transaction do
begin
category = @course_module.course_second_categories.create!(name: params[:name].strip, category_type: @course_module.module_type,
course_id: @course.id, position: @course_module.course_second_categories.count + 1)
render :json => {category_id: category.id, status: 0, message: "添加成功"}
rescue Exception => e
uid_logger_error(e.message)
tip_exception("添加子目录失败")
end
end
end
private
def set_module
@course_module = CourseModule.find_by!(id: params[:id])
@course = @course_module.course
end
end

View File

@ -1,60 +0,0 @@
class CourseSecondCategoriesController < ApplicationController
before_action :require_login, :check_auth
before_action :set_category
before_action :teacher_allowed
# 目录重命名
def rename_category
tip_exception("毕设子目录不能重命名") if @category.category_type == "graduation"
tip_exception("名称不能为空") if params[:name].blank?
tip_exception("已存在同名子目录") if @course_module.course_second_categories.exists?(name: params[:name].strip)
@category.update_attributes!(name: params[:name].strip)
normal_status(0, "更新成功")
end
# 子目录的拖动
def move_category
tip_exception("移动失败") if params[:position].blank?
unless params[:position].to_i == @category.position
if params[:position].to_i < @category.position
@course_module.course_second_categories.where("position < #{@category.position} and position >= ?", params[:position]).update_all("position = position + 1")
else
@course_module.course_second_categories.where("position > #{@category.position} and position <= ?", params[:position]).update_all("position = position - 1")
end
@category.update!(position: params[:position])
normal_status(0, "移动成功")
else
normal_status(-1, "位置没有变化")
end
end
def destroy
tip_exception("毕设子目录不能删除") if @category.category_type == "graduation"
ActiveRecord::Base.transaction do
begin
@course_module.course_second_categories.where("position > #{@category.position}").update_all("position = position - 1")
# 更新相应对象的子目录id
if @course_module.module_type == "shixun_homework"
@category.homework_commons.update_all(course_second_category_id: 0)
@right_url = "/courses/#{@course.id}/shixun_homeworks/#{@course_module.id}"
elsif @course_module.module_type == "attachment"
Attachment.where(course_second_category_id: @category.id).update_all(course_second_category_id: 0)
@right_url = "/courses/#{@course.id}/files/#{@course_module.id}"
end
@category.destroy
rescue Exception => e
uid_logger_error(e.message)
tip_exception("删除子目录失败")
end
end
end
private
def set_category
@category = CourseSecondCategory.find_by!(id: params[:id])
@course_module = @category.course_module
@course = @course_module.try(:course)
end
end

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
class DepartmentsController < ApplicationController
skip_before_action :check_sign
def for_option
render_ok(departments: current_school.departments.without_deleted.select(:id, :name).as_json)
end
private
def current_school
@_current_school ||= School.find(params[:id])
end
end

View File

@ -1,6 +0,0 @@
class DisciplinesController < ApplicationController
def index
end
end

View File

@ -1,29 +0,0 @@
class EduDatasController < ApplicationController
before_action :find_game
skip_before_action :user_setup
skip_before_action :setup_laboratory
# layout :false
include GitHelper
# params[:game_id]
def game
@shixun = @challenge.shixun
@shixun_env = @shixun.mirror_name
@shixun_tags = @challenge.challenge_tags.map(&:name)
end
def code_lines
path = @challenge.path
myshixun = @game.myshixun
# content = git_fle_content(myshixun.repo_path, path) || ""
@content = {"content":"#coding=utf-8\n\n#请在此处添加代码完成输出“Hello Python”,注意要区分大小写!\n###### Begin ######\n\n\n\n###### End ######\n\n"}
@content[:content].include?("Begin")
end
private
def find_game
game_id = params[:game_id]
@game = Game.find(game_id)
@challenge = @game.challenge
end
end

View File

@ -1,92 +0,0 @@
class ExaminationBanksController < ApplicationController
include PaginateHelper
before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public, :revoke_item]
before_action :find_exam, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public, :revoke_item]
before_action :identity_auth, only: [:index]
def index
exams = ExaminationBankQuery.call(params)
@exams_count = exams.size
@exams = paginate exams.includes(:user, :examination_items)
end
def show
@items = @exam.examination_items
@single_questions = @items.where(item_type: "SINGLE")
@multiple_questions = @items.where(item_type: "MULTIPLE")
@judgement_questions = @items.where(item_type: "JUDGMENT")
@program_questions = @items.where(item_type: "PROGRAM")
end
def create
ActiveRecord::Base.transaction do
exam = ExaminationBank.new(user: current_user)
# 保存试卷基础信息
exam = ExaminationBanks::SaveExaminationBankService.call(exam, form_params)
# 将试题篮中的试题发送到试卷,试卷的题目与试题独立
current_user.item_baskets.includes(:item_bank).each do |basket|
item = basket.item_bank
if item.present?
new_item = ExaminationItem.new
new_item.new_item(item, exam, basket.score, basket.position)
end
end
current_user.item_baskets.destroy_all
end
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def edit; end
def update
ExaminationBanks::SaveExaminationBankService.call(@exam, form_params)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def destroy
ActiveRecord::Base.transaction do
ApplyAction.where(container_type: "ExaminationBank", container_id: @exam.id).destroy_all
@exam.destroy!
render_ok
end
end
def set_public
tip_exception(-1, "该试卷已公开") if @exam.public?
tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @exam.id, container_type: "ExaminationBank", status: 0).exists?
ApplyAction.create!(container_id: @exam.id, container_type: "ExaminationBank", user_id: current_user.id)
# @exam.update_attributes!(public: 1)
render_ok
end
def revoke_item
item = @exam.examination_items.find_by!(item_bank_id: params[:item_id])
ActiveRecord::Base.transaction do
@exam.examination_items.where(item_type: item.item_type).where("position > #{item.position}").update_all("position = position -1")
item.destroy!
end
render_ok
end
private
def form_params
params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: [])
end
def find_exam
@exam = ExaminationBank.find_by!(id: params[:id])
end
def edit_auth
current_user.admin_or_business? || @exam.user == current_user
end
end

View File

@ -1,108 +0,0 @@
class ExaminationIntelligentSettingsController < ApplicationController
before_action :require_login
before_action :certi_identity_auth, only: [:create, :optinal_items, :save_exam, :exchange_one_item, :exchange_items]
before_action :find_exam, only: [:exchange_one_item, :exchange_items, :save_exam]
def optinal_items
sub_discipline_id = params[:sub_discipline_id]
tag_discipline_id = params[:tag_discipline_id]
difficulty = params[:difficulty]
source = params[:source]
items = OptionalItemQuery.call(sub_discipline_id, tag_discipline_id, difficulty, source)
@single_question_count = items.select{ |item| item.item_type == "SINGLE" }.size
@multiple_question_count = items.select{ |item| item.item_type == "MULTIPLE" }.size
@judgement_question_count = items.select{ |item| item.item_type == "JUDGMENT" }.size
@program_question_count = items.select{ |item| item.item_type == "PROGRAM" }.size
end
def create
ActiveRecord::Base.transaction do
exam = ExaminationIntelligentSetting.new(user: current_user)
# 保存试卷基础信息
exam = ExaminationIntelligentSettings::SaveSettingService.call(exam, form_params)
render_ok({exam_setting_id: exam.id})
end
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def save_exam
new_exam = ExaminationBank.new(user: current_user)
# 保存试卷基础信息
ExaminationIntelligentSettings::SaveExaminationService.call(new_exam, save_params, @exam)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def exchange_one_item
item = @exam.item_baskets.find_by!(item_bank_id: params[:item_id])
exam_type_setting = @exam.examination_type_settings.find_by!(item_type: item.item_type)
# 获取可选的题
items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public)
# 可选题中去掉已组卷的试题
type_items = items.select{ |t_item| t_item.item_type == item.item_type }
optional_item_ids = (type_items.pluck(:id) - @exam.item_baskets.where(item_type: item.item_type).pluck(:item_bank_id)).uniq
# 如果可选的题数等于0则提示无可换的题
tip_exception("无可换的题") if optional_item_ids.size == 0
new_item = ItemBank.find optional_item_ids.sample(1).first
ActiveRecord::Base.transaction do
@exam.item_baskets << ItemBasket.new(item_bank_id: new_item.id, position: item.position, score: item.score, item_type: new_item.item_type)
item.destroy!
end
render_ok
end
def exchange_items
exam_type_setting = @exam.examination_type_settings.find_by!(item_type: params[:item_type])
choosed_items = @exam.item_baskets.where(item_type: params[:item_type])
# 获取可选的题
items = OptionalItemQuery.call(@exam.sub_discipline_id, @exam.tag_discipline_containers.pluck(:tag_discipline_id), @exam.difficulty, @exam.public)
type_items = items.select{ |t_item| t_item.item_type == params[:item_type] }
# 可选题中去掉已组卷的试题
choosed_item_ids = choosed_items.pluck(:item_bank_id)
optional_item_ids = (type_items.pluck(:id) - choosed_item_ids).uniq
# 如果可选的题数等于0则提示无可换的题
tip_exception("无可换的题") if optional_item_ids.size == 0
# 如果可选题数小于设置的题数n则在原来的选题中随机选n个确保换题时能选到新的题
if optional_item_ids.size < exam_type_setting.count
absence_count = exam_type_setting.count - optional_item_ids.size
optional_item_ids = optional_item_ids + choosed_item_ids.sample(absence_count)
end
ActiveRecord::Base.transaction do
# 取试题分数
score = choosed_items.first&.score || (params[:item_type] == "PROGRAM" ? 10 : 5)
choosed_items.destroy_all
optional_item_ids.sample(exam_type_setting.count).each_with_index do |item_id, index|
new_item = ItemBank.find item_id
@exam.item_baskets << ItemBasket.new(item_bank_id: new_item.id, position: index+1, score: score, item_type: new_item.item_type)
end
end
render_ok
end
private
def find_exam
@exam = ExaminationIntelligentSetting.find_by!(id: params[:id])
tip_exception(403,"无权限编辑") unless current_user.admin_or_business? || @exam.user_id == current_user.id
end
def form_params
params.permit(:discipline_id, :sub_discipline_id, :difficulty, :source, tag_discipline_id: [], question_settings: %i[item_type count])
end
def save_params
params.permit(:name, :duration)
end
end

View File

@ -1,85 +0,0 @@
class ExaminationItemsController < ApplicationController
before_action :require_login
before_action :certi_identity_auth, only: [:create, :destroy, :delete_item_type, :set_score, :batch_set_score, :adjust_position]
before_action :validate_score, only: [:set_score, :batch_set_score]
before_action :find_exam, only: [:create, :batch_set_score, :delete_item_type]
before_action :find_item, except: [:create, :batch_set_score, :delete_item_type]
before_action :edit_auth
def create
ExaminationItems::SaveItemService.call(current_user, create_params, @exam)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def destroy
ActiveRecord::Base.transaction do
@exam.examination_items.where(item_type: @item.item_type).where("position > #{@item.position}").update_all("position = position -1")
@item.destroy!
end
render_ok
end
def delete_item_type
items = @exam.examination_items.where(item_type: params[:item_type])
items.destroy_all
render_ok
end
def set_score
@item.update_attributes!(score: params[:score])
@questions_score = @exam.examination_items.where(item_type: @item.item_type).pluck(:score).sum
@all_score = @exam.examination_items.pluck(:score).sum
render_ok({questions_score: @questions_score, all_score: @all_score})
end
def batch_set_score
@exam.examination_items.where(item_type: params[:item_type]).update_all(score: params[:score])
@questions_score = @exam.examination_items.where(item_type: params[:item_type]).pluck(:score).sum
@all_score = @exam.examination_items.pluck(:score).sum
render_ok({questions_score: @questions_score, all_score: @all_score})
end
def adjust_position
same_items = @exam.examination_items.where(item_type: @item.item_type)
max_position = same_items.size
tip_exception("position超出范围") unless params[:position].present? && params[:position].to_i <= max_position && params[:position].to_i >= 1
ActiveRecord::Base.transaction do
if params[:position].to_i > @item.position
same_items.where("position > #{@item.position} and position <= #{params[:position].to_i}").update_all("position=position-1")
@item.update_attributes!(position: params[:position])
elsif params[:position].to_i < @item.position
same_items.where("position < #{@item.position} and position >= #{params[:position].to_i}").update_all("position=position+1")
@item.update_attributes!(position: params[:position])
else
return normal_status(-1, "排序无变化")
end
end
render_ok
end
private
def find_exam
@exam = ExaminationBank.find_by!(id: params[:exam_id])
end
def create_params
params.permit(item_ids: [])
end
def find_item
@item = ExaminationItem.find_by!(id: params[:id])
@exam = @item.examination_bank
end
def validate_score
tip_exception("分值不能为空") unless params[:score].present?
tip_exception("分值需大于0") unless params[:score].to_f > 0
end
def edit_auth
current_user.admin_or_business? || @exam.user == current_user
end
end

View File

@ -1,400 +0,0 @@
class FilesController < ApplicationController
include MessagesHelper
before_action :require_login, :check_auth, except: %i[index]
before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project]
before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish]
before_action :file_validate_sort_type, only: :index
before_action :validate_send_message_to_course_params, only: :bulk_send
before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project]
before_action :validate_upload_params, only: %i[upload import]
before_action :find_file, only: %i[show setting update]
before_action :publish_params, only: %i[upload import update]
SORT_TYPE = %w[created_on downloads quotes]
def index
sort = params[:sort] || 0 # 0: 降序1: 升序
sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序
@course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
@user = current_user
@attachments = @course_second_category_id.to_i == 0 ? @course.attachments.includes(:course_second_category) : @course.attachments.by_course_second_category_id(@course_second_category_id)
@attachments = @attachments.includes(author: [:user_extension, :course_members])
.ordered(sort: sort.to_i, sort_type: sort_type.strip)
get_category(@course, @course_second_category_id)
@total_count = @attachments.size
if @user.course_identity(@course) == 5
member = @course.course_members.find_by(user_id: current_user.id, is_active: 1)
if member.try(:course_group_id).to_i == 0
@attachments = @attachments.published.unified_setting
else
not_atta_ids = @course.attachment_group_settings.none_published.where("course_group_id = #{member.try(:course_group_id)}").pluck(:attachment_id)
@attachments = @attachments.where.not(id: not_atta_ids).published
end
elsif @user.course_identity(@course) > 5
@attachments = @attachments.publiced.published
end
@publish_count = @attachments.published.size
@unpublish_count = @total_count - @publish_count
@attachments = @attachments.by_keywords(params[:search])
@attachments = @attachments.page(@page).per(@page_size)
end
def bulk_publish
return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5
# tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
attachments = @course.attachments.by_ids(@attachment_ids)
ActiveRecord::Base.transaction do
# 有分班设置时
# if @course.course_group_module? && @course.course_groups_count != 0 && params[:group_ids]
# group_ids = params[:group_ids]&.reject(&:blank?)
# charge_group_ids = @course.charge_group_ids(current_user)
# publish_groups = charge_group_ids & group_ids if group_ids
#
# attachments.each do |atta|
# if atta.published? && !atta.unified_setting || !atta.published?
# create_atta_group_settings atta
# atta.update_attributes!(unified_setting: 0) if atta.unified_setting
# none_publish_settings = atta.attachment_group_settings.where(course_group_id: publish_groups).none_published
# none_publish_settings.update_all(publish_time: Time.now)
# end
# end
# end
# 未发布的资源更新状态
attachments.where(is_publish: 0).update_all(is_publish: 1, publish_time: Time.now)
end
render_ok
end
def bulk_delete
ActiveRecord::Base.transaction do
begin
@course.attachments.by_ids(@attachment_ids).destroy_all
rescue Exception => e
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def bulk_send
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@course)
course_ids = params[:to_course_ids]
begin
@attachment_ids.each do |id|
@attachment = @course.attachments.find_by_id id
course_ids.each do |course_id|
course = Course.find_by_id course_id
unless @attachment.nil? || course.nil?
course.attachments << course.attachments.build(@attachment.attributes.except("id").merge(
quotes: 0,
downloads: 0,
author_id: current_user.id,
created_on: Time.now,
course_second_category_id: 0 # TODO 暂时只支持发送到其他课堂的主目录
))
end
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def bulk_move
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@course)
to_category_id = params[:to_category_id] || 0 # 默认移动到主目录
unless to_category_id == 0
course_second_category = @course.course_second_categories.find_by_id to_category_id
return normal_status(2, "参数to_category_id有误该目录不存在") if course_second_category.nil?
end
begin
@course.attachments.by_ids(@attachment_ids).update_all(course_second_category_id: to_category_id)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def bulk_public
@user = current_user
return normal_status(403, "您没有权限进行该操作") unless @user.teacher_of_course?(@course)
@course.attachments.by_ids(@attachment_ids).update_all(is_public: 1)
end
def public_with_course_and_project
@attachments = Attachment.publiced.simple_columns
.contains_course_and_project
.includes(:container, author: :user_extension)
.by_filename_or_user_name(params[:search])
.ordered(sort: 0, sort_type: 'created_on')
@total_count = @attachments.size
@attachments = @attachments.page(@page).per(@page_size)
end
def mine_with_course_and_project
@current_user = current_user
@attachments = Attachment.mine(current_user)
.simple_columns
.contains_course_and_project
.by_keywords(params[:search])
.ordered(sort: 0, sort_type: 'created_on')
@total_count = @attachments.size
@attachments = @attachments.page(@page).per(@page_size)
end
# 上传资源
def upload
attachment_ids = params[:attachment_ids]
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
# is_unified_setting = params.has_key?(:is_unified_setting) ? params[:is_unified_setting] : true
# publish_time = params[:publish_time]
# course_group_publish_times = params[:course_group_publish_times] || []
begin
attachment_ids.each do |attchment_id|
attachment = Attachment.find_by_id attchment_id
unless attachment.nil?
attachment.container = @course
attachment.course_second_category_id = course_second_category_id
attachment.description = params[:description]
attachment.is_public = params[:is_public] && @course.is_public == 1 ? 1 : 0
attachment.is_publish = @atta_is_publish
attachment.delay_publish = @atta_delay_publish
attachment.publish_time = @atta_publish_time
attachment.unified_setting = @unified_setting
if @unified_setting == 0
attachment_group_setting attachment, params[:group_settings]
end
# attachment.set_publish_time(publish_time) if is_unified_setting
# attachment.set_course_group_publish_time(@course, course_group_publish_times) if @course.course_groups.size > 0 && !is_unified_setting && publish_time.blank?
attachment.save!
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
# 选用资源 & 导入资源
def import
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@course) || current_user.student_of_course?(@course)
attachment_ids = params[:attachment_ids]
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
begin
attachment_ids.each do |attachment_id|
ori = Attachment.find_by_id(attachment_id)
# 同一个资源可以多次发送到课堂
# @course.attachments.each do |att|
# @exist = false
# if att.id == ori.id || (!att.copy_from.nil? && !ori.copy_from.nil? && att.copy_from == ori.copy_from) || att.copy_from == ori.id || att.id == ori.copy_from
# att.created_on = Time.now
# att.save
# @exist = true
# break
# end
# end
#
# next if @exist
attach_copied_obj = ori.copy
attach_copied_obj.container = @course
attach_copied_obj.created_on = Time.now
attach_copied_obj.author = current_user
attach_copied_obj.is_public = 0
attach_copied_obj.is_publish = @atta_is_publish
attach_copied_obj.delay_publish = @atta_delay_publish
attach_copied_obj.publish_time = @atta_publish_time
attach_copied_obj.unified_setting = @unified_setting
if @unified_setting == 0
attachment_group_setting attach_copied_obj, params[:group_settings]
end
attach_copied_obj.course_second_category_id = course_second_category_id
attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from
if attach_copied_obj.attachtype == nil
attach_copied_obj.attachtype = 4
end
attach_copied_obj.save
ori.update_columns(quotes: ori.quotes.to_i + 1)
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
# 资源设置
def update
return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@course) >= 5 && @file.author != current_user
is_public = params[:is_public]
@old_attachment = @file
@new_attachment = Attachment.find_by_id params[:new_attachment_id]
begin
unless @new_attachment.nil?
@new_attachment_history = @old_attachment.become_history
@new_attachment_history.save!
old_course_second_category_id = @old_attachment.course_second_category_id
@old_attachment.copy_attributes_from_new_attachment(@new_attachment)
@old_attachment.course_second_category_id = old_course_second_category_id
@old_attachment.save!
@new_attachment.delete
end
@old_attachment.is_public = is_public == true && @course.is_public == 1 ? 1 : 0
@old_attachment.is_publish = @atta_is_publish
@old_attachment.delay_publish = @atta_delay_publish
@old_attachment.publish_time = @atta_publish_time
@old_attachment.unified_setting = @unified_setting
if @unified_setting == 0
attachment_group_setting @old_attachment, params[:group_settings]
else
@old_attachment.attachment_group_settings.destroy_all
end
if params[:description] && !params[:description].strip.blank? && params[:description] != @old_attachment.description
@old_attachment.description = params[:description]
end
# @old_attachment.set_public(is_public)
# if is_unified_setting
# @old_attachment.set_publish_time(publish_time)
# @old_attachment.attachment_group_settings.destroy_all
# end
# if publish_time.blank? && @course.course_groups.size > 0 && !is_unified_setting
# @old_attachment.set_course_group_publish_time(@course, course_group_publish_times)
# end
@old_attachment.save!
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def show
return normal_status(403, "您没有权限进行该操作") if !current_user.teacher_of_course?(@course) && current_user != @file.author
@attachment_histories = @file.attachment_histories
end
def histories
@user = current_user
@file = @course.attachments.find_by_id params[:id]
return normal_status(-2, "该课程下没有id为 #{params[:id]}的资源") if @file.nil?
return normal_status(403, "您没有权限进行该操作") if @user != @file.author && !@user.teacher_of_course?(@course) && !@file.public?
@attachment_histories = @file.attachment_histories
end
def get_category(course, category_id)
if category_id == 0
category = course.attachment_course_modules.first
@category_id = category.try(:id)
@category_name = category.try(:module_name)
else
category = CourseSecondCategory.find category_id
@category_id = category.try(:id)
@category_name = category.try(:name)
end
end
private
def find_file
@file = Attachment.find params[:id]
end
def find_attachment_ids(attachment_ids = params[:attachment_ids])
return normal_status(-2, "参数attachment_ids不能为空") if attachment_ids.blank?
return normal_status(-2, "参数attachment_ids格式错误") if !attachment_ids.is_a? Array
end
def find_course_second_category_id
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
if course_second_category_id != 0
course_second_category = CourseSecondCategory.find_by(id: course_second_category_id, category_type: "attachment")
return normal_status(-2, "未来找到course_second_category为 #{course_second_category_id} 的目录") if course_second_category.nil?
end
end
def find_ids
@attachment_ids = params[:ids] || []
find_attachment_ids(@attachment_ids)
end
def file_validate_sort_type
normal_status(-2, "参数sort_type暂时只支持 'created_on', 'quotes', 'downloads'") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
def validate_upload_params
find_attachment_ids
find_course_second_category_id
end
def publish_params
tip_exception("缺少发布参数") if params[:delay_publish].blank?
@unified_setting = 1
# if params[:delay_publish].to_i == 1 && @course.course_group_module? && @course.course_groups_count != 0
# tip_exception("分班发布设置不能为空") if params[:group_settings].blank?
# min_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).min
# max_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).max
# tip_exception("分班发布设置不能为空") if min_publish_time.blank?
#
# # 分班设置中的时间一样且包含所有分班 则按统一设置处理,否则是非统一设置
# @unified_setting = 0 unless min_publish_time == max_publish_time && params[:group_settings].pluck(:group_id).flatten.sort == @course.course_groups.pluck(:id).sort
# els
if params[:delay_publish].to_i == 1
tip_exception("缺少延期发布的时间参数") if params[:publish_time].blank?
min_publish_time = params[:publish_time]
end
@atta_is_publish = params[:delay_publish].to_i == 1 && min_publish_time.to_time > Time.now ? 0 : 1
@atta_delay_publish = params[:delay_publish].to_i
@atta_publish_time = params[:delay_publish].to_i == 1 ? min_publish_time : Time.now
end
def create_atta_group_settings atta
if atta.attachment_group_settings.size != @course.course_groups.size
@course.course_groups.where.not(id: atta.attachment_group_settings.pluck(:course_group_id)).each do |group|
atta.attachment_group_settings << AttachmentGroupSetting.new(course_group_id: group.id, course_id: @course.id,
publish_time: atta.publish_time)
end
end
end
def attachment_group_setting attachment, group_setting
create_atta_group_settings attachment
group_setting.each do |setting|
tip_exception("分班id不能为空") if setting[:group_id].length == 0
tip_exception("发布时间不能为空") if setting[:publish_time].blank?
AttachmentGroupSetting.where(attachment_id: attachment.id, course_group_id: setting[:group_id]).
update_all(publish_time: setting[:publish_time])
end
end
end

View File

@ -1,5 +1,6 @@
class ForksController < ApplicationController
before_action :require_login, :find_project_with_id
before_action :require_login
before_action :load_project
before_action :authenticate_project!, :authenticate_user!
def create
@ -8,8 +9,13 @@ class ForksController < ApplicationController
private
def authenticate_project!
return if current_user != @project.owner
render_result(1, "自己不能fork自己的项目")
if current_user&.id == @project.user_id
render_result(-1, "自己不能fork自己的项目")
elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier)
render_result(-1, "fork失败你已拥有了这个项目")
end
# return if current_user != @project.owner
# render_result(-1, "自己不能fork自己的项目")
end
def authenticate_user!

View File

@ -1,84 +0,0 @@
class GitsController < ApplicationController
skip_before_action :check_sign
# 说明:
# 以下Git认证只针对新版gitGitlab的Git认证不走该控制器
# 思路:
# 1、用户通过Git客户端推送代码的时候这个时候Git客户端肯定会强制用户输入邮箱的
# 2、通过web端版本库界面更新代码如果用户邮箱不存在则用系统备用邮箱
# 供 git-workhorse反向调用认证
def auth
# HTTP_AUTHORIZATION: "Basic 这里base64编码的的密码(user:passwd)"
decodes = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
rand_code = decodes.sample(10).join
logger.info("11111112222223333 HTTP_AUTHORIZATION: #{request.env["HTTP_AUTHORIZATION"]}")
logger.info("1111111 git auth start: code is #{rand_code}, time is #{Time.now}")
# logger.info("#########-----request_env: #{request.env}")
# {"service"=>"git-receive-pack", "controller"=>"gits", "action"=>"auth",
# "url"=>"forge01/cermyt39.git/info/refs"}
#
gituser = edu_setting('git_username')
gitpassword = edu_setting('git_password')
result = false
if request.env["HTTP_AUTHORIZATION"] && request.env["HTTP_AUTHORIZATION"].split(" ").length == 2
username_password = Base64.decode64(request.env["HTTP_AUTHORIZATION"].split(" ")[1])
if username_password.split(":")[0].nil? || username_password.split(":")[1].nil?
result = false
else
input_username = username_password.split(":")[0].strip()
input_password = username_password.split(":")[1].strip()
uid_logger("git start auth: input_username is #{input_username}")
# Git 超级权限用户
if input_username.strip == gituser.strip && input_password.strip == gitpassword.strip
result = true
else
# 用户是否对对象拥有权限
system_user = User.find_by_login(input_username) || User.find_by_mail(input_username) || User.find_by_phone(input_username)
# 如果用户名密码错误
if system_user.blank? || system_user && !system_user.check_password?(input_password)
uid_logger_error("git start: password is wrong")
result = false
else
git_url = params["url"]
username = git_url.split("/")[0]
shixunname = git_url.split("/")[1].split(".")[0]
repo_name = username + "/" + shixunname
uid_logger("git start: repo_name is #{repo_name}")
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).where(repo_name: repo_name).first
if shixun.blank?
shixun_id = ShixunSecretRepository.where(repo_name: repo_name).pluck(:shixun_id).first
logger.info("####repo_name:#{repo_name}")
logger.info("####shixun_id:#{shixun_id}")
shixun = Shixun.select([:id, :user_id, :repo_name, :identifier]).find_by(id: shixun_id)
end
uid_logger("git start auth: shixun identifier is #{shixun.try(:identifier)}")
uid_logger("git start auth: systemuser is #{system_user.try(:login)}")
if shixun.present?
logger.info("#######{system_user.manager_of_shixun?(shixun)}")
if system_user.present? && system_user.manager_of_shixun?(shixun)
result = true
else
uid_logger_error("gituser is not shixun manager")
result = false
end
else
uid_logger_error("shixun is not exist")
# result = false
result = true # 为了测试跳出
end
end
end
end
end
authenticate_or_request_with_http_basic do |username, password|
result
end
end
end

View File

@ -1,755 +0,0 @@
class GraduationTasksController < ApplicationController
before_action :require_login, :check_auth, except: [:index]
before_action :find_course, except: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment,
:cross_comment_setting, :assign_works, :commit_comment_setting, :sonar]
before_action :find_task, only: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment,
:cross_comment_setting, :assign_works, :commit_comment_setting, :sonar]
before_action :user_course_identity
before_action :task_publish, only: [:show, :show_comment, :tasks_list, :settings]
before_action :teacher_allowed, only: [:new, :create, :edit, :update, :set_public,:multi_destroy, :publish_task, :end_task,
:update_settings, :add_to_bank, :cross_comment_setting, :assign_works, :commit_comment_setting]
before_action :require_id_params, only: [:set_public ,:multi_destroy, :publish_task, :end_task, :add_to_bank]
before_action :valid_params, only: [:update_settings]
before_action :allow_cross_comment, only: [:cross_comment_setting, :assign_works, :commit_comment_setting]
include ExportHelper
def index
search = "#{params[:search].to_s.strip.downcase}"
order = params[:order]
page = params[:page] ? params[:page].to_i : 1
default_order = "IF(ISNULL(graduation_tasks.publish_time),0,1), graduation_tasks.publish_time DESC, graduation_tasks.created_at DESC"
@identity = current_user.course_identity(@course)
if @identity < Course::STUDENT
@tasks = @course.graduation_tasks.where("graduation_tasks.name like ?", "%#{search}%")
else
@tasks = @course.graduation_tasks.where("graduation_tasks.name like ? and publish_time <= '#{Time.now}'", "%#{search}%")
end
if order.present? && order != "all"
if @course.is_end
@tasks = @tasks.none
elsif order.to_i == 4 # 补交
@tasks = @tasks.where("status > 1 and allow_late = 1 and (late_time is null or late_time > '#{Time.now}')")
else
@tasks = @tasks.where(status: order)
end
end
@member = @course.course_members.find_by(user_id: current_user.id, is_active: 1)
@all_count = @course.graduation_tasks.size
@published_count = @course.graduation_tasks.where("publish_time <= '#{Time.now}'").size
@task_count = @tasks.size
@tasks = @tasks.reorder("#{default_order}").page(page).per(15).includes(:graduation_works)
end
# 任务问答
def show
@attachments = @task.attachments
@current_user = current_user
end
# 毕设任务列表
def tasks_list
# 搜索栏数据
@current_user = current_user
# 分页参数
page = params[:page] || 1
limit = params[:limit] || 20
@work = @task.graduation_works.where(user_id: current_user.id)
@students = @course.students
@assign_power = @user_course_identity < Course::STUDENT && @task.cross_comment && @task.comment_status == 2
#end_time @task.allow_late ? @task.late_time : @task.end_time
# 任务发布的情况下: 是老师身份或者任务已截止的情况下公开任务了作品设置的学生也能查看其他人的作品
if @task.published? && (@user_course_identity < Course::STUDENT ||
(@user_course_identity == Course::STUDENT && @work.present? && @work.take.work_status > 0 &&
((!@task.allow_late && @task.status > 1) || (@task.allow_late && @task.late_time && @task.late_time < Time.now)) &&
(@task.open_work || @task.open_score)))
_tasks_list
# 排序
rorder = params[:order].blank? ? "update_time" : params[:order]
b_order = params[:b_order].blank? ? "desc" : params[:b_order]
if rorder == "update_time" || 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
@view_work = @task.open_work || @user_course_identity < Course::STUDENT
@work_count = @work_list.count
@work_excel = @work_list
@work_list = @work_list.page(page).per(limit)
if params[:format] == "xlsx"
complete_works = @work_excel.where("work_status > 0").size
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
elsif complete_works == 0
normal_status(-1,"暂无用户提交")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
set_export_cookies
graduation_work_to_xlsx(@work_excel,@task,current_user)
task_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@task.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{task_export_name_.strip}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column}
}
end
end
elsif params[:format] == "zip"
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
zip_works = @work_excel.where("work_status > 0")
status = checkfileSize(zip_works)
if status == 0
if params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
respond_to do |format|
format.zip{
set_export_cookies
zipfile = zip_homework_common @task, zip_works
file = decode64(zipfile[0][:base64file])
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
}
end
end
else
normal_status(status,status == -2 ? "500M" : "无附件可下载")
end
end
end
else
@work_list = !@task.published? ? [] : @work
@view_work = false
@work_count = @work_list.count
@all_work_count = @work_list.count
if params[:format] == "xlsx" || params[:format] == "zip"
normal_status(-1,"毕设任务未发布")
end
end
end
# 评论列表接口、 包含一级和二级评论的获取
def show_comment
@page = params[:page] || 1
@limit = params[:limit] || 10
@parent = params[:parent_id]
@current_user = current_user
@messages = @task.journals_for_messages
@messages_count = @messages.count
if @parent
@messages = @messages.where(m_parent_id: @parent).order("created_on asc")
else
@messages = @messages.parent_comment.order("created_on desc")
end
@messages = @messages.page(@page).per(@limit)
end
def create
ActiveRecord::Base.transaction do
begin
@graduation_task = GraduationTask.new(graduation_task_params)
@graduation_task.course_id = @course.id
@graduation_task.user_id = current_user.id
@graduation_task.base_on_project = @graduation_task.task_type == 2 ? 1 : 0
if @graduation_task.save!
# 为学生创建作品
@graduation_task.create_work_list
Attachment.associate_container(params[:attachment_ids], @graduation_task.id, @graduation_task.class) if params[:attachment_ids]
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def new
left_banner_content = @course.course_modules.search_by_module_type("graduation")
if left_banner_content.present?
banner = left_banner_content.first.course_second_categories.last
@left_banner_id = banner.id
@left_banner_name = banner.name
else
normal_status(-1,"左侧导航不存在!")
end
end
def edit
left_banner_content = @course.course_modules.search_by_module_type("graduation")
if left_banner_content.present?
banner = left_banner_content.first.course_second_categories.last
@left_banner_id = banner.id
@left_banner_name = banner.name
end
end
def update
ActiveRecord::Base.transaction do
begin
@task.update_attributes(graduation_task_params)
Attachment.associate_container(params[:attachment_ids], @task.id, @task.class) if params[:attachment_ids]
normal_status(0, "更新成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# 代码检测
def sonar
tip_exception(403, "无权限访问") unless current_user.admin_or_business?
_tasks_list
@work_list = @work_list.where("work_status > 0")
person_list = @work_list.map do |work|
o = {
name: "#{work.user&.real_name}",
uid: "#{work.user&.student_id}",
downloadUrl: ''
}
attachment = work.attachments.last
if attachment
o[:downloadUrl] = "#{edu_setting('host_name')}"+download_url(attachment)
end
o
end
filename = "#{@task.name}_#{Time.now.strftime('%Y%m%d%H%M%S')}.json"
json = File.open("/tmp/#{filename}", "w+")
json.puts(person_list.to_json)
json.close
send_file json.path, filename: filename
end
# 设为公开
def set_public
tip_exception("仅公开课堂才能公开毕设任务") if @course.is_public == 0
tasks = @course.graduation_tasks.where(id: params[:task_ids])
tasks.update_all(is_public: 1)
normal_status(0, "更新成功")
end
# 删除多个任务
def multi_destroy
ActiveRecord::Base.transaction do
begin
tasks = @course.graduation_tasks.where(id: params[:task_ids])
tasks.destroy_all
# 这些写是因为model中的关联删除无法删除is_delete=0的作品
GraduationWork.where(graduation_work_id: tasks.pluck(:id)).destroy_all
normal_status(0, "删除成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# 加入题库
def add_to_bank
ActiveRecord::Base.transaction do
begin
tasks = @course.graduation_tasks.where(id: params[:task_ids])
tasks.each do |task|
task_bank = current_user.gtask_banks.find_by(graduation_task_id: task.id)
# 已加入的更新,未加入的新建
if task_bank.present?
task_bank.update_attributes(name: task.name, description: task.description, course_list_id: @course.course_list_id,
min_num: task.min_num, max_num: task.max_num, base_on_project: task.base_on_project)
task_bank.attachments.destroy_all
else
task_bank = GtaskBank.new(name: task.name, description: task.description, user_id: current_user.id,
task_type: task.task_type, quotes: 1, graduation_task_id: task.id,
min_num: task.min_num, max_num: task.max_num, base_on_project: task.base_on_project,
course_list_id: @course.course_list_id)
task_bank.save!
task.update_attributes!(gtask_bank_id: task_bank.id)
end
task.attachments.each do |attachment|
att = attachment.copy
att.author_id = task_bank.user_id
att.copy_from = attachment.id
task_bank.attachments << att
end
end
normal_status(0,"加入题库成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def publish_task
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间必须晚于当前时间") if params[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
# ActiveRecord::Base.transaction do
begin
tasks = @course.graduation_tasks.where(id: params[:task_ids], status: 0).
where("publish_time is null or publish_time > '#{Time.now}'")
tasks.each do |task|
task.publish_time = Time.now
task.status = 1
task.end_time = params[:end_time]
# 补交结束时间
task.late_time = Time.at(task.end_time.to_i + 30*24*3600) if task.allow_late && task.late_time.nil?
task.save!
GraduationTaskPublishNotifyJob.perform_later(task.id)
task.act_as_course_activity
end
normal_status(0, "发布成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
# end
end
def end_task
ActiveRecord::Base.transaction do
begin
tasks = @course.graduation_tasks.where(id: params[:task_ids], status: 1)
tasks.each do |task|
task.end_time = Time.now
task.status = 2
task.save!
end
normal_status(0, "更新成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def settings
@current_user = current_user
end
def update_settings
ActiveRecord::Base.transaction do
begin
unless @course.is_end
# 分组设置 已有提交作品或关联项目的,则“基于项目实施”不能修改, 已有提交作品的人数限制的范围只能扩大,不能缩小
if @task.task_type == 2
@task.min_num = @task.student_commit_works ? (params[:min_num].to_i > @task.min_num ? @task.min_num : params[:min_num])
: params[:min_num]
@task.max_num = @task.student_commit_works ? (params[:max_num].to_i < @task.max_num ? @task.max_num : params[:max_num])
: params[:max_num]
unless @task.student_relate_projects
tip_exception("base_on_project参数不能为空") if params[:base_on_project].blank?
@task.base_on_project = params[:base_on_project].to_i
end
end
# 发布设置
if @task.status == 0
tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("发布时间不能早于当前时间") if params[:publish_time].to_time <= Time.now
tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now
tip_exception("截止时间必须晚于发布时间") if params[:publish_time].to_time >= params[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day
@task.publish_time = params[:publish_time]
@task.end_time = params[:end_time]
if @task.publish_time <= Time.now
@task.status = 1
send_tiding = true
end
elsif @task.status < 2
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
@task.end_time = params[:end_time]
end
# 补交设置
# @task.allow_late = params[:allow_late]
# @task.late_penalty = params[:allow_late].to_i == 1 ? params[:late_penalty] : 0
current_late_penalty = @task.late_penalty
if params[:allow_late].to_i == 1
tip_exception("补交结束时间不能为空") if params[:late_time].blank?
tip_exception("补交结束时间不能早于截止时间") if params[:late_time] <= @task.end_time
tip_exception("补交结束时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:late_time] > strf_time(@course.end_date.end_of_day)
tip_exception("迟交扣分应为正整数") if params[:late_penalty] && params[:late_penalty].to_i < 0
@task.allow_late = true
@task.late_time = params[:late_time]
@task.late_penalty = params[:late_penalty].to_i
else
@task.allow_late = false
@task.late_penalty = 0
end
# 迟交扣分有变动则更新迟交学生的成绩
if @task.late_penalty != current_late_penalty
@task.graduation_works.where(work_status: 2).each do |work|
work.late_penalty = @task.late_penalty
work.save!
end
end
# 评分设置
unless @task.cross_comment && @task.comment_time && @task.comment_time < Time.now
@task.cross_comment = params[:cross_comment].to_i
tip_exception("评阅时间不能为空") if @task.cross_comment && params[:comment_time].blank?
tip_exception("评阅时间应当大于截止时间") if @task.cross_comment && params[:comment_time] <= @task.end_time
@task.comment_time = @task.cross_comment ? params[:comment_time] : nil
@task.comment_status = 2 if @task.cross_comment && @task.comment_status == 0
@task.graduation_work_comment_assignations.destroy_all if !@task.cross_comment
# 去掉评阅设置
# @task.comment_num = @task.cross_comment ? params[:comment_num].to_i : 3
# @task.comment_status = @task.cross_comment ? params[:comment_status] : 0
# if @task.cross_comment && params[:comment_status].to_i == 4
# tip_exception("评阅数不能为空") if params[:comment_num].blank?
# tip_exception("评阅数应大于0") if params[:comment_num].to_i < 1
#
# @course.graduation_groups.each_with_index do |group, index|
# ass_group = @task.graduation_task_group_assignations.find_by(graduation_group_id: group.id)
# if ass_group.present? && params[:comment_group][index].present? && params[:comment_group][index] != "0"
# ass_group.update_attributes(assign_graduation_group_id: params[:comment_group][index])
# else
# @task.graduation_task_group_assignations << GraduationTaskGroupAssignation.new(graduation_group_id: group.id,
# assign_graduation_group_id: params[:comment_group][index])
# end
# end
# end
end
# 公开设置
@task.open_work = params[:open_work] ? params[:open_work].to_i : 0
@task.open_score = params[:open_score] ? params[:open_score].to_i : 0
@task.save!
if send_tiding
GraduationTaskPublishNotifyJob.perform_later(@task.id)
@task.act_as_course_activity
end
normal_status(0, "更新成功")
else
tip_exception("课堂已结束不能再更新")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def cross_comment_setting
@comment_status = params[:comment_status] || (@task.cross_comment ? @task.comment_status : 2)
group_ids = @course.charge_group_ids(current_user)
@course_groups = @course.course_groups.where(id: group_ids)
# 如果传了分班id则取合集
group_ids = group_ids & params[:group_ids].map(&:to_i) unless params[:group_ids].blank?
page = params[:page] ? params[:page].to_i : 1
limit = params[:limit] ? params[:limit].to_i : 10
# 取所有课堂的作品
if group_ids.sort == @course.course_groups.pluck(:id).sort
@work_list = @task.graduation_works
else
@work_list = @task.graduation_works.joins("join course_members on graduation_works.user_id=course_members.user_id").
where(course_members: {course_group_id: group_ids})
end
@user_count = @work_list.size
@work_list = @work_list.page(page).per(limit).includes(user: [:user_extension])
@students = @course.students.where(user_id: @work_list.pluck(:user_id))
end
def assign_works
tip_exception("请先选择作品") if params[:work_ids].blank?
tip_exception("请指定要分配的老师或答辩组") if params[:user_ids].blank? && params[:graduation_group_ids].blank?
ActiveRecord::Base.transaction do
begin
works = @task.graduation_works.where(id: params[:work_ids])
# 手动分配:分配给老师
if !params[:user_ids].blank?
@task.update_attributes(comment_status: 2)
works.each do |work|
# 之前分配的老师但现在未分配时需要删除
work.graduation_work_comment_assignations.where.not(user_id: params[:user_ids]).destroy_all
@course.teachers.where(user_id: params[:user_ids]).pluck(:user_id).uniq.each do |user_id|
unless work.graduation_work_comment_assignations.exists?(user_id: user_id)
GraduationWorkCommentAssignation.create!(graduation_task_id: @task.id, graduation_work_id: work.id,
user_id: user_id)
end
end
end
# 答辩组分配:分配答辩组
elsif !params[:graduation_group_ids].blank?
@task.update_attributes(comment_status: 4)
works.each do |work|
work.graduation_task_group_assignations.where.not(graduation_group_id: params[:graduation_group_ids]).destroy_all
@course.graduation_groups.where(id: params[:graduation_group_ids]).pluck(:id).uniq.each do |graduation_group_id|
unless work.graduation_task_group_assignations.exists?(graduation_group_id: graduation_group_id)
GraduationTaskGroupAssignation.create!(graduation_task_id: @task.id, graduation_work_id: work.id,
graduation_group_id: graduation_group_id)
end
end
end
end
normal_status("分配成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def commit_comment_setting
tip_exception("type参数有误") if params[:type].blank? || !["commit", "cancel"].include?(params[:type])
ActiveRecord::Base.transaction do
begin
# 提交弹框
# if params[:type] == "commit"
# tip_exception("comment_status参数有误") if params[:comment_status].blank? || ![2, 4].include?(params[:comment_status].to_i)
# @task.update_attributes(comment_status: params[:comment_status])
# if params[:comment_status].to_i == 2
# @task.temporary_graduation_work_comment_assignations.update_all(temporary: 0) # 临时数据转正
# @task.delete_graduation_work_comment_assignations.destroy_all # 删除置了删除位的数据
# @task.graduation_task_group_assignations.destroy_all # 删除答辩组分配数据
# else
# @task.temporary_graduation_task_group_assignations.update_all(temporary: 0)
# @task.delete_graduation_task_group_assignations.destroy_all
# @task.graduation_work_comment_assignations.destroy_all
#
# GraduationTaskCrossCommentJob.perform_later(@task.id)
# end
# else
# # 取消时删除临时数据,恢复删除位数据
# @task.temporary_graduation_work_comment_assignations.destroy_all # 删除临时数据
# @task.delete_graduation_work_comment_assignations.update_all(temporary: 0) # 恢复置了删除位的数据
#
# @task.temporary_graduation_task_group_assignations.destroy_all # 删除临时数据
# @task.delete_graduation_task_group_assignations.update_all(temporary: 0) # 恢复置了删除位的数据
# end
normal_status("操作成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
private
def find_task
begin
@task = GraduationTask.find(params[:id])
@course = @task.course
rescue Exception => e
uid_logger(e.message)
tip_exception("id不存在")
end
end
# 未发布时非老师角色不能访问,发布后非课堂成员不能访问未公开的任务
def task_publish
if (@user_course_identity >= Course::STUDENT && @task.status < 1) ||
(@user_course_identity > Course::STUDENT && (@course.is_public == 0 || !@task.is_public))
tip_exception(-1,"任务还未发布,无法查看")
end
end
def graduation_task_params
tip_exception("类型参数不能为空") if params[:task_type].blank?
tip_exception("名称不能为空") if params[:name].blank?
tip_exception("名称不能超过60个字符") if params[:name].length > 60 #6.11 -hs
tip_exception("描述不能为空") if params[:description].blank?
params.require(:graduation_task).permit(:task_type, :name, :description)
end
def require_id_params
tip_exception("请至少选择一个毕设任务") if params[:task_ids].blank?
tip_exception("批量设置不能超过15个") if params[:task_ids].length > 15
end
def valid_params
if @task.task_type == 2
tip_exception("最小人数不能为空") if params[:min_num].blank?
tip_exception("最大人数不能为空") if params[:max_num].blank?
tip_exception("最小人数不能少于1") if params[:min_num].to_i <= 0
tip_exception("最大人数不能小于最小人数要求") if params[:min_num].to_i > params[:max_num].to_i
end
end
def allow_cross_comment
tip_exception("请先开启交叉评阅再设置") unless @task.cross_comment
end
def _tasks_list
# 如有有分班则看分班内的学生,否则看所有学生的作品
user_ids =
if @user_course_identity < Course::STUDENT
@course.teacher_group_user_ids(current_user.id)
else
course_group_id = @course.course_member(current_user.id).course_group_id
@course.students.where(course_group_id: course_group_id).pluck(:user_id)
end
@work_list = @task.graduation_works.where(user_id: user_ids).includes(user: [:user_extension])
@all_work_count = @work_list.count
@teachers = @course.teachers.where.not(user_id: current_user.id).includes(:user)
# 教师评阅搜索 0: 未评, 1 已评
unless params[:teacher_comment].blank?
graduation_work_ids = GraduationWorkScore.where(graduation_work_id: @work_list.map(&:id)).pluck(:graduation_work_id)
if params[:teacher_comment].to_i == 0
@work_list = @work_list.where("work_status != 0")
elsif params[:teacher_comment].to_i == 1
@work_list = @work_list.where("work_status != 0").where(id: graduation_work_ids)
end
end
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交
unless params[:task_status].blank?
@work_list = @work_list.where(work_status: params[:task_status])
end
# 分班情况
unless params[:course_group].blank?
group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id)
# 有分组只可能是老师身份查看列表
@work_list = @work_list.where(user_id: group_user_ids)
end
# 只看我的交叉评阅
unless params[:cross_comment].blank?
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 = @task.graduation_works.where(id: graduation_work_id)
end
# 组员、组长作品的筛选
if @task.task_type == 2 && !params[:member_work].blank?
if params[:member_work].to_i == 1
@work_list = @work_list.where("user_id = commit_user_id")
elsif params[:member_work].to_i == 0
@work_list = @work_list.where("user_id != commit_user_id")
end
end
# 输入姓名和学号搜索
# TODO user_extension 如果修改 请调整
unless params[:search].blank?
@work_list = @work_list.joins(user: :user_extension).where("concat(lastname, firstname) like ?
or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
end
#
# def graduation_work_to_xls items
# xls_report = StringIO.new
# book = Spreadsheet::Workbook.new
# sheet1 = book.create_worksheet :name => "学生成绩"
# blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10
# sheet1.row(0).default_format = blue
# course = @task.course
# count_row = 1
# list = 0
# if @task.task_type == 1
# if @task.cross_comment
# sheet1.row(0).concat(["学生id","真实姓名", "登录名", "学号", "电子邮箱", "分班", "作品描述", "教师评分","交叉评分", "迟交扣分",
# "成绩", "更新时间"])
# else
# sheet1.row(0).concat(["学生id", "真实姓名", "登录名", "学号", "电子邮箱", "分班", "作品描述", "教师评分", "迟交扣分",
# "成绩", "更新时间"])
# end
# items.each do |work|
# sheet1[count_row,list] = work.user.id
# sheet1[count_row,list+=1] = work.user.full_name
# sheet1[count_row,list+=1] = work.user.login
# sheet1[count_row,list+=1] = work.user.student_id
# sheet1[count_row,list+=1] = work.user.mail
# sheet1[count_row,list+=1] = work.class_grouping_name
# sheet1[count_row,list+=1] = strip_html work.description if work.description
# sheet1[count_row,list+=1] = work.teacher_score.nil? ? "未评分" : work.teacher_score.round(1)
# if @task.cross_comment
# sheet1[count_row,list+=1] = work.cross_score.nil? ? "未评分" : work.cross_score.round(1)
# end
# sheet1[count_row,list+=1] = work.late_penalty
# sheet1[count_row,list+=1] = work.respond_to?("work_score") ? work.work_score.nil? ? "未评分" : work.work_score.round(1) : "未评分"
# sheet1[count_row,list+=1] = format_time(work.update_time)
# count_row += 1
# list = 0
# end
# elsif @task.task_type == 2
# if @task.cross_comment
# sheet1.row(0).concat(["分组", "组员","分班", "作品描述", "教师评分","交叉评分","迟交扣分", "成绩", "更新时间"])
# else
# sheet1.row(0).concat(["分组", "组员","分班", "作品描述", "教师评分", "迟交扣分", "成绩", "更新时间"])
# end
# items.each do |work|
# sheet1[count_row,list] = work.group_id
# sheet1[count_row,list+=1] = work.user.full_name
# sheet1[count_row,list+=1] = work.class_grouping_name
# sheet1[count_row,list+=1] = strip_html work.description if work.description
# sheet1[count_row,list+=1] = work.teacher_score.nil? ? "未评分" : work.teacher_score.round(1)
# if @task.cross_comment
# sheet1[count_row,list+=1] = work.cross_score.nil? ? "未评分" : work.cross_score.round(1)
# end
# sheet1[count_row,list+=1] = work.late_penalty
# sheet1[count_row,list+=1] = work.respond_to?("work_score") ? work.work_score.nil? ? "未评分" : work.work_score.round(1) : "未评分"
# sheet1[count_row,list+=1] = format_time(work.update_time)
# count_row += 1
# list = 0
# end
# end
# book.write xls_report
# xls_report.string
# end
end

View File

@ -1,568 +0,0 @@
class GraduationWorksController < ApplicationController
before_action :require_login, :check_auth
before_action :find_task, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project, :delete_work]
before_action :find_work, only: [:show, :edit, :update, :revise_attachment, :supply_attachments, :comment_list,
:add_score, :delete_score, :adjust_score, :assign_teacher]
before_action :user_course_identity
before_action :task_public
before_action :teacher_allowed, only: [:add_score, :adjust_score, :assign_teacher]
before_action :course_student, only: [:new, :create, :edit, :update, :search_member_list, :relate_project,
:cancel_relate_project, :delete_work]
before_action :my_work, only: [:edit, :update, :revise_attachment]
before_action :published_task, only: [:new, :create, :edit, :update, :search_member_list, :relate_project,
:cancel_relate_project, :revise_attachment]
before_action :edit_duration, only: [:edit, :update, :delete_work]
before_action :open_work, only: [:show, :supply_attachments, :comment_list]
def new
if @task.task_type == 2 && @task.base_on_project
work = @task.graduation_works.where(user_id: current_user.id).first
if work.present? && (work.work_status != 0 || work.project_id == 0)
normal_status(403, "")
end
end
@user = current_user
end
# 搜索课堂学生
def search_member_list
unless params[:search].blank?
# 有搜索条件时搜索课堂所有学生包括已提交的
users = User.joins(:graduation_works).where("concat(users.lastname, users.firstname) like ? and
graduation_task_id = #{@task.id}", "%#{params[:search]}%")
user_ids = users.pluck(:id) - [current_user.id]
@members = @course.students.where(user_id: user_ids)
else
# 没有搜索条件时搜索课堂所有未提交的学生
user_ids = @task.graduation_works.where("work_status = 0").pluck(:user_id) - [current_user.id]
@members = @course.students.where(user_id: user_ids)
end
page = params[:page] ? params[:page].to_i : 1
limit = params[:limit] ? params[:limit].to_i : 10
# todo user_extension
@members = @members.page(page).per(limit).includes(:course_group, user: :user_extension)
end
def delete_work
ActiveRecord::Base.transaction do
begin
work = @task.graduation_works.find_by!(user_id: params[:user_id])
tip_exception("只有组长才能删除组员") if work.commit_user_id != current_user.id
work.update!(description: nil, project_id: 0, late_penalty: 0, work_status: 0, commit_time: nil,
update_time: nil, group_id: 0, commit_user_id: nil, final_score: nil, work_score: nil,
teacher_score: nil, teaching_asistant_score: nil, update_user_id: nil)
work.attachments.destroy_all
work.tidings.destroy_all
normal_status("删除成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
end
end
end
# 判断项目是否已有其他作品关联上了
def check_project
tip_exception("项目id不能为空") if params[:project_id].blank?
work = @task.graduation_works.where(project_id: params[:project_id]).first
@is_relate = work.present?
@relate_user = work.present? ? work.user.real_name : ""
end
def relate_project
tip_exception("项目id不能为空") if params[:project_id].blank?
ActiveRecord::Base.transaction do
begin
# 判断项目是否存在且当前用户是项目管理员
project = Project.where(id: params[:project_id]).first
member = Member.where(project_id: project.try(:id), user_id: current_user.id).first
if project.present? && member.present? && member.member_roles.first.try(:role_id) == 3
work = @task.graduation_works.where("user_id = #{current_user.id}").first ||
GraduationWork.create(user_id: current_user.id, graduation_task_id: @task.id, course_id: @task.course_id)
if work.work_status == 0 && work.project_id == 0
work.update!(project_id: project.id, update_time: Time.now)
# 将老师加入项目
project_member = project.members.where(user_id: @task.user_id).first
if project_member.present?
project_member.member_roles.first.update!(role_id: 3) if project_member.member_roles.first.present?
else
member = Member.create(user_id: @task.user_id, project_id: project.id)
member.member_roles << MemberRole.new(role_id: 3)
Tiding.create(user_id: @task.user_id, trigger_user_id: current_user.id, container_id: project.id,
container_type: 'ManagerJoinProject', belong_container_id: project.id,
belong_container_type: "Project", tiding_type: "System", extra: 3)
end
normal_status("关联成功")
else
tip_exception("不能重复关联项目")
end
else
tip_exception("该项目不存在")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def cancel_relate_project
work = @task.graduation_works.where(user_id: current_user.id, work_status: 0).first
if work.present? && work.project.present?
ActiveRecord::Base.transaction do
begin
member = work.project.members.where(user_id: @task.user_id).first
member.destroy if member.present?
Tiding.where(user_id: @task.user_id, trigger_user_id: current_user.id, container_id: work.project.id,
container_type: 'ManagerJoinProject').destroy_all
work.update!(project_id: 0)
normal_status("取消关联成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
else
tip_exception("无法取消关联")
end
end
def create
graduation_work = @task.graduation_works.where(user_id: current_user.id).first ||
GraduationWork.create(user_id: current_user.id, graduation_task_id: @task.id, course_id: @task.course_id)
update_check graduation_work
tip_exception("作业不可重复提交") if graduation_work.work_status != 0
tip_exception("已过了提交时间") if @course.is_end || (@task.end_time < Time.now && (!@task.allow_late ||
(@task.late_time.present? && @task.late_time < Time.now)))
student_ids = [current_user.id]
ActiveRecord::Base.transaction do
begin
# work.update_attributes(graduation_work_params)
graduation_work.description = params[:description]
graduation_work.commit_time = Time.now
graduation_work.update_time = Time.now
graduation_work.commit_user_id = current_user.id
graduation_work.update_user_id = current_user.id
graduation_work.course_id = @course.id
graduation_work.group_id = @task.task_type == 2 ? @task.graduation_works.where("work_status != 0").map(&:group_id).max.to_i + 1 : 0
#提交作品时,计算是否迟交
graduation_work.late_penalty = @task.end_time < Time.now.to_s ? @task.late_penalty : 0
graduation_work.work_status = @task.end_time < Time.now.to_s ? 2 : 1
if graduation_work.save!
Attachment.associate_container(params[:attachment_ids], graduation_work.id, graduation_work.class)
if @task.task_type == 2
members = (params[:user_ids] || []).collect(&:to_i) - [current_user.id]
members = @course.students.pluck(:user_id) & members
student_ids += members
for i in 0 .. members.count-1
stu_work = @task.graduation_works.where(user_id: members[i].to_i).first || GraduationWork.new
stu_work.update!(user_id: members[i].to_i, description: graduation_work.description,
graduation_task_id: @task.id, project_id: graduation_work.project_id,
late_penalty: graduation_work.late_penalty, work_status: graduation_work.work_status,
commit_time: Time.now, update_time: Time.now, group_id: graduation_work.group_id,
commit_user_id: current_user.id, update_user_id: current_user.id)
stu_work.save!
graduation_work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
stu_work.attachments << att
end
end
end
@task.update_column(:updated_at, Time.now)
# todo 更新对应的毕设任务课堂动态
# update_course_activity(@taskhomework.class,@task.id)
@work_id = graduation_work.id
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
SubmitGraduationWorkNotifyJob.perform_later(@task.id, student_ids)
end
end
def edit
@task_user = current_user
if @task.task_type == 2
@commit_user_id = @work.commit_user_id
@work_members = @course.students.where(user_id: @task.graduation_works.where(group_id: @work.group_id).pluck(:user_id)).
order("course_members.id=#{@work.commit_user_id} desc").includes(:course_group, user: :user_extension)
end
end
def update
update_check @work
student_ids = []
ActiveRecord::Base.transaction do
begin
@work.description = params[:description]
@work.update_time = Time.now
@work.update_user_id = current_user.id
# @work.commit_user_id = current_user.id
if @work.save!
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class)
#如果学生作品被打分后修改,应该给老师提示
student_ids << @work.user_id if @work.scored?
if @task.task_type == 2
graduation_works = @task.graduation_works.where("group_id = #{@work.group_id} and user_id != #{@work.user_id}")
work_user_ids = graduation_works.pluck(:user_id)
params_user_ids = (params[:user_ids] || []).collect(&:to_i) - [@work.user_id]
params_user_ids = @course.students.pluck(:user_id) & params_user_ids
# 原成员更新描述、更新时间以及附件
@task.graduation_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work|
work.update!(update_time: Time.now, description: @work.description, update_user_id: current_user.id)
work.attachments.destroy_all
@work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
work.attachments << att
end
student_ids << work.user_id if work.scored?
end
# 删除的成员
delete_user_ids = work_user_ids - params_user_ids
@task.graduation_works.where(group_id: @work.group_id, user_id: delete_user_ids).each do |work|
work.attachments.destroy_all
# work.student_works_scores.destroy_all
work.tidings.destroy_all
end
@task.graduation_works.where(group_id: @work.group_id, user_id: delete_user_ids).
update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil,
final_score: nil, teacher_score: nil, work_score: nil, project_id: 0, group_id: 0,
commit_user_id: nil, update_user_id: nil)
# 新增加的成员
(params_user_ids - work_user_ids).each do |user_id|
stu_work = @task.graduation_works.where(user_id: user_id).empty? ? GraduationWork.new :
@task.graduation_works.where(user_id: user_id).first
stu_work.update!(user_id: user_id, description: @work.description, graduation_task_id: @task.id,
project_id: @work.project_id, late_penalty: @work.late_penalty,
work_status: @work.work_status, commit_time: Time.now, update_time: Time.now,
group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id)
@work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
stu_work.attachments << att
end
student_ids << user_id
end
end
normal_status("更新成功")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
SubmitGraduationWorkNotifyJob.perform_later(@task.id, student_ids) if student_ids.present?
end
end
def show
@current_user = current_user
@is_author = @work.user_id == current_user.id
@work_members = @task.task_type == 1 ? [] : @task.graduation_works.where.not(user_id: @work.user_id).
where(group_id: @work.group_id).includes(:user)
@attachments = @work.attachments.where("attachtype != 7 or attachtype is null")
end
def comment_list
@current_user = current_user
@last_comment = @work.graduation_work_scores.where(user_id: @current_user.id).last
@comment_scores = @work.graduation_work_scores.reorder("created_at desc").includes(:user)
end
# 给作品评分
def add_score
tip_exception("该学生的分数已经过调整,不能再评阅") if @work.ultimate_score
tip_exception("分数和评语不能都为空") if params[:score].blank? && params[:comment].blank?
tip_exception("分数不能超过0-100") if params[:score] && (params[:score].to_f < 0 || params[:score].to_f > 100)
ActiveRecord::Base.transaction do
begin
# 没传score则取上次评分成绩
score = GraduationWorkScore.where(user_id: current_user.id, graduation_work_id: @work.id).last
new_score = GraduationWorkScore.new
new_score.score = params[:score].blank? ? score.try(:score) : params[:score].to_f
new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != ""
new_score.user_id = current_user.id
new_score.graduation_work_id = @work.id
new_score.graduation_task_id = @task.id
# 如果作品是未提交的状态则更新为已提交
if !new_score.score.nil? && @work.work_status == 0
@work.update!(work_status: 1, commit_time: Time.now)
if @task.task_type == 2
@work.update!(group_id: @task.graduation_works.where("work_status != 0").select("distinct group_id").count + 1)
end
end
if @task.cross_comment && @work.graduation_work_comment_assignations.where(user_id: current_user.id).count > 0
new_score.reviewer_role = 2
else
new_score.reviewer_role = 1
end
if new_score.save!
Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class)
# 该用户的历史评阅无效
score.update_column('is_invalid', true) if score.present? && score.score.present?
Tiding.create(user_id: @work.user_id, trigger_user_id: User.current.id, container_id: new_score.id,
container_type: "GraduationWorkScore", parent_container_id: @work.id,
parent_container_type: "GraduationWork", belong_container_id: @task.course_id,
belong_container_type: "Course", viewed: 0, tiding_type: "GraduationTask", extra: new_score.reviewer_role)
case new_score.reviewer_role
when 1 #教师评分取平均分
ts_score = GraduationWorkScore.find_by_sql("SELECT AVG(score) AS score FROM graduation_work_scores WHERE
graduation_work_id = #{@work.id} AND reviewer_role = 1 AND score IS NOT NULL AND is_invalid = 0")
@work.teacher_score = ts_score.first.score.nil? ? nil : ts_score.first.score.try(:round, 2).to_f
# 分组作业整组同评
if @task.task_type == 2 && params[:same_score]
add_graduation_score_to_member @work, @task, new_score
end
when 2 #交叉评分显示平均分
ts_score = GraduationWorkScore.find_by_sql("SELECT AVG(score) AS score FROM graduation_work_scores WHERE
graduation_work_id = #{@work.id} AND reviewer_role = 2 AND score IS NOT NULL AND is_invalid = 0")
@work.cross_score = ts_score.first.score.nil? ? nil : ts_score.first.score.try(:round, 2).to_f
end
@task.update_column('updated_at', Time.now)
# update_course_activity(@task.class, @task.id)
@work.save!
normal_status("提交成功")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def adjust_score
tip_exception("成绩不能为空") if params[:score].blank?
tip_exception("成绩不能小于零") if params[:score].to_f < 0
tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100
tip_exception("调分原因不能超过100个字符") if params[:comment].present? && params[:comment].length > 100
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效
@work.graduation_work_scores.where.not(score: nil).update_all(is_invalid: 1)
new_score = GraduationWorkScore.new(graduation_work_id: @work.id, score: params[:score].to_f,
graduation_task_id: @task.id, comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}",
user_id: User.current.id, reviewer_role: 1, is_ultimate: 1)
new_score.save!
@work.update!(ultimate_score: 1, work_score: params[:score].to_f)
Tiding.create!(user_id: @work.user_id, trigger_user_id: current_user.id, container_id: new_score.id,
container_type: "AdjustScore", parent_container_id: @task.id,
parent_container_type: "GraduationTask", belong_container_id: @course.id,
belong_container_type: 'Course', tiding_type: "GraduationTask")
normal_status("调分成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# 删除教师/教辅的评分记录
def delete_score
score = @work.graduation_work_scores.where(id: params[:comment_id]).first
if score.present? && (score.is_invalid || score.score.nil?) && (score.user == current_user || current_user.admin_or_business?)
begin
score.destroy
normal_status("删除成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
else
tip_exception("无法删除")
end
end
def supply_attachments
@revise_attachments = @work.attachments.where(attachtype: 7)
@last_atta = @revise_attachments.last
end
def revise_attachment
tip_exception("不在补交阶段内") if @course.is_end || @task.end_time > Time.now || !@task.allow_late ||
(@task.late_time && @task.late_time < Time.now)
tip_exception("附件参数有误") if params[:attachment_ids].blank? || !params[:attachment_ids].is_a?(Array)
tip_exception("补交附件原因不能为空") if params[:description].blank?
ActiveRecord::Base.transaction do
begin
revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last
if revise_attachment.present? && @work.graduation_work_scores.where("created_at > '#{revise_attachment.created_on}'
and score is not null").count == 0
revise_attachment.destroy
end
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7)
revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "GraduationWork").last
revise_attachment.update!(description: params[:description]) if revise_attachment.present?
@work.update!(update_time: Time.now)
normal_status("提交成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# 交叉评阅分配老师
def assign_teacher
tip_exception(-1, "user_id不能为空") if params[:user_id].nil?
@work_assign_teacher = @work.graduation_work_comment_assignations.find_by(user_id: params[:user_id])
if @work_assign_teacher.present?
# graduation_group_id: 已经是答辩组的需要 将答辩组清空
@work_assign_teacher.update!(graduation_group_id: 0)
else
@work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(graduation_task_id: @task.id,
user_id: params[:user_id],
graduation_group_id: 0)
end
normal_status("分配成功")
end
private
def find_task
begin
@task = GraduationTask.find(params[:graduation_task_id])
@course = @task.course
rescue Exception => e
uid_logger(e.message)
tip_exception("id不存在")
end
end
def find_work
begin
@work = GraduationWork.find(params[:id])
@task = @work.graduation_task
@course = @task.course
rescue Exception => e
uid_logger(e.message)
tip_exception("id不存在")
end
end
def task_public
tip_exception(403,"没有操作权限") if @user_course_identity > Course::STUDENT && (@course.is_public == 0 ||
(@course.is_public == 1 && !@task.is_public))
end
def course_student
tip_exception(403,"没有操作权限") if @user_course_identity != Course::STUDENT
end
def my_work
tip_exception(403,"没有操作权限") if @work.user_id != current_user.id || @work.work_status == 0
end
def published_task
tip_exception("不能在非提交时间内操作") if @task.status == 0 || (!@task.allow_late && @task.status > 1) ||
(@task.allow_late && @task.late_time && @task.late_time < Time.now)
end
def edit_duration
tip_exception("已过了修改时间") if @task.end_time && @task.end_time < Time.now
end
# 作品是否公开
def open_work
tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @task.open_work)
end
def update_check work
tip_exception("作品描述不能为空") if params[:description].blank?
if @task.task_type == 2
tip_exception("小组成员不能为空") if params[:user_ids].blank?
tip_exception("小组成员人数不合要求") if params[:user_ids].length > @task.max_num || params[:user_ids].length < @task.min_num
tip_exception("请先关联项目") if @task.base_on_project && work.project_id == 0
end
end
def graduation_work_params
params.require(:graduation_work).permit(:description)
end
def add_graduation_score_to_member work, task, new_score
graduation_works = task.graduation_works.where("group_id = #{work.group_id} and id != #{work.id} and ultimate_score = 0")
graduation_works.each do |st_work|
st_score = GraduationWorkScore.new(user_id: new_score.user_id, score: new_score.score,
reviewer_role: new_score.reviewer_role, comment: new_score.comment)
st_work.graduation_work_scores << st_score
score = GraduationWorkScore.where(user_id: new_score.user_id, graduation_work_id: st_work.id).last
# 该用户的历史评阅无效
score.update_column('is_invalid', true) if score.present? && score.score.present?
teacher_score = GraduationWorkScore.find_by_sql("SELECT AVG(score) AS score FROM graduation_work_scores WHERE
graduation_work_id = #{work.id} AND reviewer_role = 1 AND score IS NOT NULL AND is_invalid = 0")
st_work.teacher_score = teacher_score.first.score.nil? ? nil : teacher_score.first.score.try(:round, 2).to_f
st_work.save!
Tiding.create(user_id: st_work.user_id, trigger_user_id: User.current.id, container_id: st_score.id,
container_type: "GraduationWorkScore", parent_container_id: st_work.id,
parent_container_type: "GraduationWork", belong_container_id: task.course_id,
belong_container_type: "Course", viewed: 0, tiding_type: "GraduationTask", extra: st_score.reviewer_role)
# 评阅附件的复制
new_score.attachments.each do |attachment|
att = attachment.copy
att.author_id = st_score.user_id
st_score.attachments << att
end
end
end
end

View File

@ -1,38 +0,0 @@
class GtopicBanksController < ApplicationController
before_action :require_login
before_action :find_bank, :bank_visit_auth
before_action :bank_admin, only: [:edit, :update]
def show
@bank_attachments = @bank.attachments
end
def edit
@attachments = @bank.attachments
end
def update
ActiveRecord::Base.transaction do
@bank.update_attributes(gtopic_bank_params)
Attachment.associate_container(params[:attachment_ids], @bank.id, @bank.class) if params[:attachment_ids]
normal_status(0, "更新成功")
end
end
private
def find_bank
@bank = GtopicBank.find_by!(id: params[:id])
end
def bank_admin
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin_or_business?
end
def gtopic_bank_params
tip_exception("name参数不能为空") if params[:gtopic_bank][:name].blank?
tip_exception("description参数不能为空") if params[:gtopic_bank][:description].blank?
params.require(:gtopic_bank).permit(:name, :topic_type, :topic_source, :topic_property_first, :description,
:topic_property_second, :source_unit, :topic_repeat, :province, :city)
end
end

View File

@ -1,220 +0,0 @@
class HackUserLastestCodesController < ApplicationController
before_action :require_login, except: [:listen_result]
before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code, :sync_code, :add_notes,
:listen_result, :result, :submit_records, :restore_initial_code]
before_action :update_user_hack_status, only: [:code_debug, :code_submit]
before_action :require_auth_identity, only: [:add_notes]
before_action :require_manager_identity, only: [:show, :update_code, :restore_initial_code, :sync_code]
skip_before_action :check_sign, only: [:listen_result]
def show
@my_hack.update_attribute(:submit_status, 0) if @my_hack.submit_status == 1
@modify = @my_hack.modify_time.to_i < @hack.hack_codes.first.modify_time.to_i
end
def update_code
@my_hack.update_attribute(:code, params[:code])
render_ok
end
# 恢复初始代码
def restore_initial_code
@my_hack.update_attribute(:code, @hack.code)
end
# 同步代码
def sync_code
@my_hack.update_attributes(code: @hack.code, modify_time: Time.now)
end
# 调试代码
def code_debug
exec_mode = "debug"
error_status = 501
error_msg = "debug_error"
oj_evaluate exec_mode, error_status, error_msg
render_ok
end
# 提交
def code_submit
exec_mode = "submit"
error_status = 502
error_msg = "submit_error"
oj_evaluate exec_mode, error_status, error_msg
render_ok
end
# 提交结果显示
def result
if @my_hack.submit_status == 1
render json: {status: 1, message: "正在评测中"}
else
@mode = params[:mode]
@result =
if @mode == "submit"
@my_hack.hack_user_codes.last
elsif @mode == "debug"
@my_hack.hack_user_debug
end
end
end
# 提交记录
def submit_records
records = @my_hack.hack_user_codes
@records_count = records.count
@records = paginate records.created_order
end
# 提交记录详情
def record_detail
@hack_user = HackUserCode.find params[:id]
set = HackSet.find_by(id: @hack_user.error_test_set_id)
@pass_set_count = set ? set.position - 1 : 0
@set_count = @hack_user.hack.hack_sets.count
@my_hack = @hack_user.hack_user_lastest_code
end
# 接收中间件返回结果接口
# 调试模式: status 0 表示评测无错误,其他 表示错误(如编译出错,执行出错,超时等)
def listen_result
logger.info("###########listen_result#{params}")
begin
ojEvaResult = JSON.parse(params[:ojEvaResult])
testCase = ojEvaResult['testCase']
# 只有编译出错时,才正则匹配错误行数
error_line=
if ojEvaResult['status'] == "4" || ojEvaResult['status'] == "5"
regular_match_error_line ojEvaResult['outPut'], @my_hack.hack.language
end
# debug 与submit 公用的参数
ds_params = {input: testCase['input'], output: testCase['output'], hack_id: @hack.id,
code: ojEvaResult['codeFileContent'], user_id: @my_hack.user_id, error_line: error_line,
status: ojEvaResult['status'], error_msg: ojEvaResult['outPut'],
execute_time: ojEvaResult['executeTime'], execute_memory: ojEvaResult['executeMem']}
ActiveRecord::Base.transaction do
# debug模式与submit模式
if ojEvaResult['execMode'] == "debug"
save_debug_data ds_params
elsif ojEvaResult['execMode'] == "submit"
save_submit_data ds_params.merge(expected_output: testCase['expectedOutput'],
error_test_set_id: ojEvaResult['failCaseNum'])
end
# 评测完成后,还原评测中的状态
@my_hack.update_attribute(:submit_status, 0)
end
render_ok
rescue Exception => e
logger.error("#########listen_result: #{e.message}")
end
end
def add_notes
@my_hack.update_attribute(:notes, params[:notes])
render_ok
end
private
def find_my_hack
@my_hack = HackUserLastestCode.find_by(identifier: params[:identifier])
@hack = @my_hack.hack
end
def oj_evaluate exec_mode, error_status, error_msg
request_url = "#{edu_setting('cloud_bridge')}/bridge/ojs/evaluate"
test_sets =
if exec_mode == "submit"
@hack.hack_sets.map{|set| {input: set.input, output: set.output, caseId: set.id}}
else
[{input: params[:input]}]
end
testCases = Base64.encode64(test_sets.to_json)
#codeFileContent = Base64.urlsafe_encode64(@my_hack.code)
debug_params = {execMode: exec_mode,
tpiID: @my_hack.identifier,
testCases: testCases,
platform: @my_hack.language,
codeFileContent: @my_hack.code,
timeLimit: @hack.time_limit,
sec_key: Time.now.to_i}
interface_json_post request_url, debug_params, error_status, error_msg
# 每次评测提交数增加
@hack.increment!(:submit_num)
end
# 正则错误行数
def regular_match_error_line content, language
content = Base64.decode64(content).force_encoding("utf-8")
logger.info("######content: #{content}")
case language
when 'Java'
content.scan(/.java.\d+/).map{|s| s.match(/\d+/)[0].to_i}.min
when 'C', 'C++'
content.scan(/\d:\d+:/).map{|s| s.match(/\d+/)[0].to_i}.min
when 'Python'
content.scan(/line \d+/).map{|s| s.match(/\d+/)[0].to_i}.min
end
end
# 存储debug数据
def save_debug_data debug_params
if @my_hack.hack_user_debug.present?
@my_hack.hack_user_debug.update_attributes!(debug_params)
else
debug = HackUserDebug.new(debug_params)
debug.hack_user_lastest_code_id = @my_hack.id
debug.save!
end
end
# 存储submit数据
def save_submit_data submit_params
# 通关
if submit_params[:status] == "0"
# 编程题已经发布,且之前未通关奖励积分
@hack.increment!(:pass_num)
if @hack.status == 1 && !@my_hack.passed?
reward_attrs = { container_id: @hack.id, container_type: 'Hack', score: @hack.score }
RewardGradeService.call(@my_hack.user, reward_attrs)
RewardExperienceService.call(@my_hack.user, reward_attrs)
# 评测完成更新通过数
@my_hack.update_attributes(passed: true, passed_time: Time.now)
end
end
# 创建用户评测记录
logger.info("###########submit_params:#{submit_params}")
query_index = @my_hack.hack_user_codes.count +1
@my_hack.hack_user_codes.create!(submit_params.merge(query_index: query_index))
end
# 调试或提交改变状态
def update_user_hack_status
@my_hack.update_attribute(:submit_status, 1)
end
# 只有自己才能改动代码
def require_identity
if @my_hack.user_id != current_user.id
tip_exception(403, "..")
end
end
# 老师、自己、管理可以查看他人的编程题
def require_manager_identity
unless current_user.certification_teacher? || admin_or_business? || @my_hack.user_id == current_user.id
tip_exception(403, "..")
end
end
# 只有自己才能评测
def require_auth_identity
unless @my_hack.user_id == current_user.id
tip_exception(403, "..")
end
end
end

View File

@ -1,282 +0,0 @@
class HacksController < ApplicationController
before_action :require_login, except: [:index]
before_action :find_hack, only: [:edit, :update, :publish, :start, :update_set, :delete_set, :destroy, :cancel_publish]
before_action :require_teacher_identity, only: [:create]
before_action :require_auth_identity, only: [:update, :edit, :publish, :update_set, :delete_set, :destroy, :cancel_publish]
# 开启编程,如果第一次开启,创建一条记录,如果已经开启过的话,直接返回标识即可
def start
# 未发布的编程题,只能作者、或管理员访问
start_hack_auth
user_hack = @hack.hack_user_lastest_codes.where(user_id: current_user.id).first
logger.info("#user_hack: #{user_hack}")
identifier =
if user_hack.present?
logger.info("#####user_hack_id:#{user_hack.id}")
user_hack.identifier
else
user_identifier = generate_identifier HackUserLastestCode, 12
user_code = {user_id: current_user.id, code: @hack.code, modify_time: Time.now,
identifier: user_identifier, language: @hack.language}
@hack.hack_user_lastest_codes.create!(user_code)
user_identifier
end
render_ok(identifier: identifier)
end
# 首页
def index
# 筛选过滤与排序
params_filter_or_order
# 我解决的编程题数
user_codes = HackUserLastestCode.joins(:hack).mine_hack(current_user).passed
@simple_count = user_codes.where(hacks: {difficult: 1}).count
@medium_count = user_codes.where(hacks: {difficult: 2}).count
@diff_count = user_codes.where(hacks: {difficult: 3}).count
@pass_count = @simple_count + @medium_count + @diff_count
@hacks_count = @hacks.count("hacks.id")
@hacks = paginate @hacks
end
def create
begin
logger.info("##########{hack_params}")
tip_exception("一次只能增加50个测试集") if hack_sets_params.size > 50
tip_exception("一次只能增加50个知识点") if params[:tags].size > 50
hack = Hack.new(hack_params)
hack.user_id = current_user.id
hack.identifier = generate_identifier Hack, 8
tag_params = params[:tags].map{|tag| {tag_discipline_id: tag}}
ActiveRecord::Base.transaction do
hack.save!
# 创建测试集与代码
hack.hack_sets.create!(hack_sets_params)
# 新建知识点
hack.tag_discipline_containers.create!(tag_params) if tag_params.present?
hack_codes = hack.hack_codes.new(hack_code_params)
hack_codes.modify_time = Time.now
hack_codes.save!
new_item_params = item_params.merge(container: hack, item_type: 'PROGRAM', difficulty: params[:hack][:difficult], user_id: current_user.id)
ItemBank.create!(new_item_params)
end
render_ok({identifier: hack.identifier})
rescue => e
logger.error("########create_hack_error: #{e.message}")
render_error("创建失败: #{e.message}")
end
end
def update
begin
# 知识点
tag_discipline_ids = @hack.tag_discipline_containers.pluck(:tag_discipline_id)
new_tag_ids = params[:tags].to_a - tag_discipline_ids
tag_params = new_tag_ids.map{|tag| {tag_discipline_id: tag}}
ActiveRecord::Base.transaction do
@hack.update_attributes!(hack_params)
set_ids = @hack.hack_sets.pluck(:id)
# 更新
param_update_sets params[:update_hack_sets], set_ids
# 新建
@hack.hack_sets.create!(hack_sets_params)
# 更新代码
code_params = params[:hack_codes][:code] != @hack.code ? hack_code_params.merge(modify_time: Time.now) : hack_code_params
@hack.hack_codes.first.update_attributes!(code_params)
@hack.tag_discipline_containers.create!(tag_params) if tag_params
@hack.tag_discipline_containers.where.not(tag_discipline_id: params[:tags]).destroy_all
# 更新题库相关记录
if @hack.item_bank.present?
update_item_params = item_params.merge({difficulty: params[:hack][:difficult]})
@hack.item_bank.update!(update_item_params)
end
end
render_ok
rescue Exception => e
logger.error("####update_hack_error: #{e.message}")
render_error("更新失败: #{e.message}")
end
end
# 更新测试集接口
def update_set
set = @hack.hack_sets.find_by(id: params[:id])
set.update_attributes!(hack_set_params)
render_ok
end
# 单独删除测试集
def delete_set
set = @hack.hack_sets.find_by(id: params[:id])
set.destroy!
render_ok
end
# 发布功能
def publish
@hack.update_attribute(:status, 1)
base_attrs = {
trigger_user_id: current_user.id, viewed: 0, tiding_type: 'System', user_id: @hack.user_id,
parent_container_type: "HackPublish", extra: @hack.identifier
}
@hack.tidings.create!(base_attrs)
render_ok
end
# 取消发布
def cancel_publish
@hack.update_attribute(:status, 0)
base_attrs = {
trigger_user_id: current_user.id, viewed: 0, tiding_type: 'System', user_id: @hack.user_id,
parent_container_type: "HackUnPublish", extra: @hack.identifier
}
@hack.tidings.create!(base_attrs)
render_ok
end
# 发布列表
def unpulished_list
limit = params[:limit] || 16
page = params[:page] || 1
hacks = Hack.where(user_id: current_user.id, status: 0)
@hacks_count = hacks.count
@hacks = hacks.includes(:hack_sets).page(page).per(limit)
end
def edit;
end
def new;
end
def destroy
begin
base_attrs = {
user_id: @hack.user_id, viewed: 0, tiding_type: 'System', trigger_user_id: current_user.id,
parent_container_type: "HackDelete", extra: "#{@hack.name}"
}
@hack.tidings.create!(base_attrs)
@hack.destroy
render_ok
rescue => e
logger.error("####hack_delete_error: #{e.message}")
render_error("删除失败")
end
end
private
# 实名认证老师,管理员与运营人员权限
def require_teacher_identity
unless current_user.certification_teacher? || admin_or_business?
tip_exception(403, "..")
end
end
# 只有自己,或者管理员才能更新
def require_auth_identity
unless @hack.user_id == current_user.id || admin_or_business?
tip_exception(403, "..")
end
end
def find_hack
@hack = Hack.find_by_identifier(params[:identifier])
end
def hack_params
params.require(:hack).permit(:name, :description, :difficult, :open_or_not, :time_limit, :score, :sub_discipline_id)
end
def item_params
params.require(:hack).permit(:name, :sub_discipline_id)
end
def hack_sets_params
params.permit(hack_sets: [:input, :output, :position])[:hack_sets]
end
def hack_set_params
params.require(:hack_set).permit(:id, :input, :output, :position)
end
def hack_code_params
params.require(:hack_codes).permit(:code, :language)
end
def publish_params
params.require(:hack).permit(:difficult, :category, :open_or_not, :time_limit, :score)
end
def param_update_sets sets, all_sets_id
delete_set_ids = all_sets_id - sets.map {|set| set[:id]}
@hack.hack_sets.where(id: delete_set_ids).destroy_all
logger.info("#######sets:#{sets}")
sets.each do |set|
logger.info("###set[:id] #{set[:id]}")
logger.info("###all_sets #{all_sets_id.include?(set[:id])}")
if all_sets_id.include?(set[:id])
update_attrs = {input: set[:input], output: set[:output], position: set[:position]}
@hack.hack_sets.find_by!(id: set[:id]).update_attributes!(update_attrs)
end
end
end
def params_filter_or_order
# 如果有来源,就不管发布公开私有
select_sql = "hacks.*, if(hacks.hack_user_lastest_codes_count=0, 0, hacks.pass_num/hacks.hack_user_lastest_codes_count) passed_rate"
if params[:come_from]
hacks = Hack.select(select_sql).mine(current_user.id)
else
# 全部包括已经发布的,和我的未发布的
if current_user.admin_or_business?
hacks = Hack.select(select_sql)
else
hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id))
end
end
# 搜索
if params[:search]
hacks = hacks.where("name like ?", "%#{params[:search]}%")
end
# 难度
if params[:difficult]
hacks = hacks.where(difficult: params[:difficult])
end
# 状态
if params[:status]
user_hacks = HackUserLastestCode.where(user_id: current_user.id)
if params[:status].to_i == -1
if user_hacks.present?
hacks = hacks.where.not(id: user_hacks.pluck(:hack_id))
end
else
hacks = hacks.joins(:hack_user_lastest_codes).where(hack_user_lastest_codes: {status: params[:status]})
end
end
# 分类
if params[:category]
hacks = hacks.where(category: params[:category])
end
# 语言
if params[:language]
hacks = hacks.joins(:hack_codes).where(hack_codes: {language: params[:language]})
end
# 排序
sort_by = params[:sort_by] || "hack_user_lastest_codes_count"
sort_direction = params[:sort_direction] || "desc"
@hacks = hacks.order("#{sort_by} #{sort_direction}")
end
def start_hack_auth
return true if @hack.status == 1
require_auth_identity
end
end

View File

@ -1,44 +0,0 @@
class HomeController < ApplicationController
def index
# banner图
images = current_laboratory.portal_images.only_online.order(position: :asc)
images = default_laboratory.portal_images.only_online.order(position: :asc) if images.blank? # 未设置时使用EduCoder的轮播图
@images_url = []
images.each do |image|
@images_url << {path: image.link, image_url: Util::FileManage.source_disk_file_url(image)}
end
# 目录分级
@rep_list = current_laboratory.shixun_repertoires
shixuns = current_laboratory.shixuns
subjects = current_laboratory.subjects
if current_laboratory.main_site?
shixuns = shixuns.where(homepage_show: true)
subjects = subjects.where(homepage_show: true)
else
shixuns = shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { homepage: true, laboratory_id: current_laboratory.id})
subjects = subjects.joins(:laboratory_subjects).where(laboratory_subjects: { homepage: true, laboratory_id: current_laboratory.id})
end
@shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8)
@subjects = subjects.includes(:repertoire, :shixuns).limit(8)
@main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8)
@main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8)
# if current_laboratory.main_site?
# @tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
# @stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
# end
end
def search
@fuzzy_searchs = params[:keyword].split(" ").join("%")
@shixuns = Shixun.where("name like ?", "%#{@fuzzy_searchs}%")
@total_count = @shixuns.count
end
end

View File

@ -0,0 +1,96 @@
class HooksController < ApplicationController
before_action :require_login
before_action :find_project_with_id
before_action :check_user
before_action :set_repository
def index
hooks_response = Gitea::Hooks::ListService.new(@user.gitea_token, @user.login, @repository.try(:identifier)).call
if hooks_response.status == 200
lists = JSON.parse(hooks_response.body)
@hooks_size = lists.size
@hooks = paginate(lists)
else
normal_status(-1, "出现错误")
end
end
def create
#根据gitea的api
# hook_params = {
# active: true,
# type: "gitea",
# branch_filter: "",
# config: {
# content_type: "application/json",
# url: "#{EduSetting.get("host_name")}/repositories/#{project.id}/repo_hooks.json",
# http_method: "post"
# },
# events: ["create", "pull", "push"],
# }
#根据gitea上hook的字段测试的
# hook_params = {
# is_active: params[:is_active] || false,
# type: params[:type],
# http_method: params[:http_method] || "POST",
# content_type: params[:content_type].to_i,
# secret: params[:secret],
# events: {
# push_only: params[:push_only] || false, # 是否为推送事件
# send_everything: params[:send_everything] || false, #是否为所有事件
# choose_events: params[:choose_events] || false, #是否为自定义事件
# branch_filter: params[:branch_filter] || "*",
# events: {
# create: params[:create] || false, #创建分支/标签
# delete: params[:delete] || false, #删除分支/标签
# fork: params[:fork] || false, #仓库被派生
# issues: params[:issues] || false, #工单
# issue_comment: params[:issue_comment] || false, #评论
# push: params[:push] || false # 推送
# pull_request: params[:pull_request] || false #合并请求
# repository: params[:repository] || false #仓库
# release: params[:release] || false #版本发布
# }
# }
# }
hook_params = params[:hook_params]
Gitea::Hooks::CreateService.new(@user, @repository.try(:identifier), hook_params).call #创建gitea的hook功能
Gitea::Hooks::CreateService.new(user, p.try(:identifier), hook_params).call #创建gitea的hook功能
end
def update
hook_params = params[:hook_params]
response = Gitea::Hooks::UpdateService.new(@user, @repository.try(:identifier), hook_params, params[:id]).call
if response.status == 200
normal_status(1, "更新成功")
else
normal_status(-1, "更新失败")
end
end
def destroy
response = Gitea::Hooks::DestroyService.new(@user, @repository.try(:identifier), params[:id]).call
if response.status == 204
normal_status(1, "删除成功")
else
normal_status(-1, "删除失败")
end
end
private
def set_repository
@repository = @project.repository
@user = @project.owner
normal_status(-1, "仓库不存在") unless @repository.present?
normal_status(-1, "用户不存在") unless @user.present?
end
def check_user
unless @project.user_id == current_user.id
tip_exception(403, "您没有权限进入")
end
end
end

View File

@ -1,7 +0,0 @@
class HotKeywordsController < ApplicationController
def index
keywords = []
keywords = HotSearchKeyword.hot(8) if HotSearchKeyword.available?
render_ok(keywords: keywords)
end
end

View File

@ -1,5 +1,7 @@
class IgnoresController < ApplicationController
def index
@ignores = Ignore.search(params[:name]).without_content
#@ignores = Ignore.search(params[:name]).without_content
q = Ignore.ransack(name_cont: params[:name])
@ignores = q.result(distinct: true)
end
end

View File

@ -11,7 +11,7 @@ class IssueDependsController < ApplicationController
}
save_issue_depend = IssueDepend.new(issue_depend)
if save_issue_depend.save
@issue.custom_journal_detail("issue_depend","", @issue.id)
@issue.custom_journal_detail("issue_depend","", @issue.id, current_user&.id)
normal_status(0, "添加依赖成功")
else
normal_status(0, "添加依赖失败")
@ -23,7 +23,7 @@ class IssueDependsController < ApplicationController
depend_issue_params = params[:id]
depend_issue = IssueDepend.find(depend_issue_params)
if depend_issue&.destroy
@issue.custom_journal_detail("destroy_issue_depend","", @issue.id)
@issue.custom_journal_detail("destroy_issue_depend","", @issue.id, current_user&.id)
normal_status(0, "删除依赖成功")
else
normal_status(-1, "删除依赖失败")

View File

@ -1,6 +1,7 @@
class IssueTagsController < ApplicationController
before_action :require_login
before_action :set_project
before_action :require_login, except: [:index]
before_action :load_repository
before_action :set_user
before_action :check_issue_permission, except: :index
before_action :set_issue_tag, only: [:edit, :update, :destroy]
@ -37,12 +38,12 @@ class IssueTagsController < ApplicationController
begin
issue_tag = IssueTag.new(tag_params.merge(project_id: @project.id, user_id: current_user.id))
if issue_tag.save
gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call
if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"])
normal_status(0, "标签创建成功")
else
normal_status(-1, "标签创建失败")
end
# gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call
# if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"])
# normal_status(0, "标签创建成功")
# else
# normal_status(-1, "标签创建失败")
# end
else
normal_status(-1, "标签创建失败")
end
@ -78,12 +79,12 @@ class IssueTagsController < ApplicationController
ActiveRecord::Base.transaction do
begin
if @issue_tag.update_attributes(tag_params)
gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call
if gitea_tag
normal_status(0, "标签更新成功")
else
normal_status(-1, "标签更新失败")
end
# gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call
# if gitea_tag
# normal_status(0, "标签更新成功")
# else
# normal_status(-1, "标签更新失败")
# end
else
normal_status(-1, "标签更新失败")
end
@ -102,12 +103,12 @@ class IssueTagsController < ApplicationController
ActiveRecord::Base.transaction do
begin
if @issue_tag.destroy
issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call
if issue_tag
normal_status(0, "标签删除成功")
else
normal_status(-1, "标签删除失败")
end
# issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call
# if issue_tag
# normal_status(0, "标签删除成功")
# else
# normal_status(-1, "标签删除失败")
# end
else
normal_status(-1, "标签删除失败")
end
@ -120,13 +121,8 @@ class IssueTagsController < ApplicationController
private
def set_project
@project = Project.find_by_identifier! params[:project_id]
@repository = @project.repository
def set_user
@user = @project.owner
normal_status(-1, "项目不存在") unless @project.present?
normal_status(-1, "仓库不存在") unless @repository.present?
normal_status(-1, "用户不存在") unless @user.present?
end
def check_issue_permission
@ -142,4 +138,4 @@ class IssueTagsController < ApplicationController
end
end
end
end

View File

@ -11,7 +11,7 @@ class IssueTimesController < ApplicationController
}
save_issue_time = IssueTime.new(issue_time)
if save_issue_time.save
@issue.custom_journal_detail("work_time",save_issue_time.id, "开始工作")
@issue.custom_journal_detail("work_time",save_issue_time.id, "开始工作", current_user&.id)
normal_status(0, "开始成功")
else
normal_status(0, "开始失败")
@ -22,16 +22,10 @@ class IssueTimesController < ApplicationController
end_type = params[:end_type].to_i
end_work_time = end_type == 0 ? "" : Time.now
last_work_time = @issue.issue_times.where(user_id: current_user.id, end_time: nil)
Rails.logger.info("######________last_work_time&.last.try(:id)_____###########{last_work_time&.first.try(:id)}")
if last_work_time.update_all(end_time: end_work_time)
if end_type == 0
message = "取消时间跟踪"
@issue.custom_journal_detail("cancel_time",last_work_time&.first.try(:id), "取消时间跟踪")
else
message = "停止工作"
@issue.custom_journal_detail("end_time",last_work_time&.first.try(:id), "停止工作")
end
message = end_type == 0 ? "取消时间跟踪" : "停止工作"
journal_time = end_type == 0 ? "cancel_time" : "end_time"
@issue.custom_journal_detail(journal_time,last_work_time&.first.try(:id), message, current_user&.id)
normal_status(0, message)
else
normal_status(0, "操作失败")

View File

@ -1,72 +1,39 @@
class IssuesController < ApplicationController
before_action :require_login, except: [:index, :show]
before_action :find_project
before_action :set_project_and_user
before_action :require_login, except: [:index, :show, :index_chosen]
before_action :load_project
before_action :set_user
before_action :check_issue_permission
before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue]
before_action :check_issue_permission, except: [:index, :show, :index_chosen]
before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue]
before_action :get_branches, only: [:new, :edit]
before_action :check_token_enough, only: [:create, :update]
include ApplicationHelper
include TagChosenHelper
def index
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
issues = @project.issues.issue_issue.includes(:user,:tracker, :priority, :version, :issue_status, :journals, :issue_times)
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
issues = @project.issues.issue_issue.issue_index_includes
issues = issues.where(is_private: false) unless @user_admin_or_member
@all_issues_size = issues.size
@open_issues_size = issues.where.not(status_id: 5).size
@close_issues_size = issues.where(status_id: 5).size
@assign_to_me_size = issues.where(assigned_to_id: current_user&.id).size
@my_published_size = issues.where(author_id: current_user&.id).size
status_type = params[:status_type].to_s #issue状态的选择
search_name = params[:search].to_s
start_time = params[:start_date]
end_time = params[:due_date]
if status_type.to_s == "1" #表示开启中的
issues = issues.where.not(status_id: 5)
elsif status_type.to_s == "2" #表示关闭中的
issues = issues.where(status_id: 5)
end
if search_name.present?
issues = issues.where("subject like ?", "%#{search_name}%")
end
if start_time&.present? || end_time&.present?
issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date)
end
issues = issues.where(author_id: params[:author_id]) if params[:author_id].present? && params[:author_id].to_s != "all"
issues = issues.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present? && params[:assigned_to_id].to_s != "all"
issues = issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present? && params[:tracker_id].to_s != "all"
issues = issues.where(status_id: params[:status_id]) if params[:status_id].present? && params[:status_id].to_s != "all"
issues = issues.where(priority_id: params[:priority_id]) if params[:priority_id].present? && params[:priority_id].to_s != "all"
issues = issues.where(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present? && params[:fixed_version_id].to_s != "all"
issues = issues.where(done_ratio: params[:done_ratio].to_i) if params[:done_ratio].present? && params[:done_ratio].to_s != "all"
issues = issues.where(issue_type: params[:issue_type].to_s) if params[:issue_type].present? && params[:issue_type].to_s != "all"
issues = issues.joins(:issue_tags).where(issue_tags: {id: params[:issue_tag_id].to_i}) if params[:issue_tag_id].present? && params[:issue_tag_id].to_s != "all"
order_type = params[:order_type] || "desc" #或者"asc"
order_name = params[:order_name] || "created_on" #或者"updated_on"
@page = params[:page]
@limit = params[:limit] || 15
@issues = issues.order("#{order_name} #{order_type}")
@issues_size = issues.size
@issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit)
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
@issues_size = scopes.size
@issues = paginate(scopes)
respond_to do |format|
format.json
format.xlsx{
set_export_cookies
export_issues(@issues)
export_name = "#{@project.name}_issues列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{export_name.strip}",template: "issues/index.xlsx.axlsx",locals: {table_columns:@table_columns,issues:@export_issues}
}
#导出功能暂未做,可以考虑隐藏
# format.xlsx{
# set_export_cookies
# export_issues(@issues)
# export_name = "#{@project.name}_issues列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
# render xlsx: "#{export_name.strip}",template: "issues/index.xlsx.axlsx",locals: {table_columns:@table_columns,issues:@export_issues}
# }
end
end
@ -129,8 +96,7 @@ class IssuesController < ApplicationController
end
def new
@all_branches = get_branches
@issue_chosen = issue_left_chosen(@project, nil)
@issue_chosen = get_associated_data(@project)
end
def create
@ -138,31 +104,8 @@ class IssuesController < ApplicationController
normal_status(-1, "标题不能为空")
elsif params[:subject].to_s.size > 255
normal_status(-1, "标题不能超过255个字符")
elsif (params[:issue_type].to_s == "2") && params[:token].to_i == 0
normal_status(-1, "悬赏的奖金必须大于0")
else
issue_params = {
subject: params[:subject],
description: params[:description],
is_private: params[:is_private] || false,
assigned_to_id: params[:assigned_to_id],
tracker_id: params[:tracker_id],
status_id: params[:status_id],
priority_id: params[:priority_id],
fixed_version_id: params[:fixed_version_id],
start_date: params[:start_date].to_s.to_date,
due_date: params[:due_date].to_s.to_date,
estimated_hours: params[:estimated_hours],
done_ratio: params[:done_ratio],
issue_type: params[:issue_type] || "1",
token: params[:token],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
closed_on: (params[:status_id].to_i == 5) ? Time.now : nil,
issue_classify: "issue",
branch_name: params[:branch_name].to_s,
author_id: current_user.id,
project_id: @project.id
}
issue_params = issue_send_params(params)
@issue = Issue.new(issue_params)
if @issue.save!
@ -188,42 +131,31 @@ class IssuesController < ApplicationController
parent_container_id: @project.id, parent_container_type: "Project",
tiding_type: 'issue', status: 0)
end
#为悬赏任务时, 扣除当前用户的积分
if params[:issue_type].to_s == "2"
post_to_chain("minus", params[:token].to_i, current_user.try(:login))
end
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
normal_status(0, "创建成功")
render json: {status: 0, message: "创建成", id: @issue.id}
else
normal_status(-1, "创建失败")
end
end
end
def edit
@all_branches = get_branches
@issue_chosen = issue_left_chosen(@project, @issue.id)
# @issue_chosen = issue_left_chosen(@project, @issue.id)
@cannot_edit_tags = @issue.issue_type=="2" && @issue.status_id == 5 #悬赏任务已解决且关闭的状态下,不能修改
@issue_attachments = @issue.attachments
end
def update
issue_params = {
subject: params[:subject],
description: params[:description],
is_private: params[:is_private] || false,
assigned_to_id: params[:assigned_to_id],
tracker_id: params[:tracker_id],
status_id: params[:status_id],
priority_id: params[:priority_id],
fixed_version_id: params[:fixed_version_id],
start_date: params[:start_date].to_s.to_date,
due_date: params[:due_date].to_s.to_date,
estimated_hours: params[:estimated_hours],
done_ratio: params[:done_ratio],
closed_on: (params[:status_id].to_i == 5) ? Time.now : nil,
issue_type: params[:issue_type],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",").to_s : "",
token: params[:token],
branch_name: params[:branch_name].to_s
}
last_token = @issue.token
last_status_id = @issue.status_id
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
@issue&.issue_tags_relates&.destroy_all
params[:issue_tag_ids].each do |tag|
@ -231,23 +163,22 @@ class IssuesController < ApplicationController
end
end
if @issue.update_attributes(issue_params)
issue_files = params[:attachment_ids]
change_files = false
issue_file_ids = []
issue_files = params[:attachment_ids]
change_files = false
issue_file_ids = []
if issue_files.present?
change_files = true
issue_files.each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
unless attachment.blank?
attachment.container = @issue
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
if issue_files.present?
change_files = true
issue_files.each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
unless attachment.blank?
attachment.container = @issue
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
end
# if params[:issue_tag_ids].present?
# issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id)
@ -263,39 +194,119 @@ class IssuesController < ApplicationController
# end
# end
if params[:status_id].to_i == 5
@issue.issue_times.update_all(end_time: Time.now)
end
@issue.create_journal_detail(change_files, issue_files, issue_file_ids)
normal_status(0, "更新成功")
if @issue.issue_type.to_s == "2" && params[:status_id].to_i == 5 && @issue.author_id != current_user.try(:id)
normal_status(-1, "不允许修改为关闭状态")
else
normal_status(-1, "更新失败")
end
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
if @issue.update_attributes(issue_params)
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
@issue.issue_times.update_all(end_time: Time.now)
@issue.update_closed_issues_count_in_project!
if @issue.issue_type.to_s == "2" && last_status_id != 5
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时才给token
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
else
post_to_chain("add", @issue.token, @issue.user.try(:login))
end
end
end
if @issue.issue_type.to_s == "2" && @issue.status_id != 5 && @issue.saved_change_to_attribute("token")
#表示修改token值
change_token = last_token - @issue.token
change_type = change_token > 0 ? "add" : "minus"
post_to_chain(change_type, change_token.abs, current_user.try(:login))
end
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id)
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")
end
end
end
def show
@user_permission = current_user.present? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user)
@user_permission = current_user.present? && current_user.logged? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user)
@issue_attachments = @issue.attachments
@issue_user = @issue.user
@issue_assign_to = @issue.get_assign_user
@join_users = join_users(@issue)
#总耗时
cost_time(@issue)
# cost_time(@issue)
#被依赖
@be_depended_issues_array = be_depended_issues(@issue)
# #被依赖
# @be_depended_issues_array = be_depended_issues(@issue)
#依赖于
depended_issues(@issue)
# #依赖于
# depended_issues(@issue)
end
def destroy
if @issue.delete
normal_status(0, "删除成功")
else
begin
issue_type = @issue.issue_type
status_id = @issue.status_id
token = @issue.token
login = @issue.user.try(:login)
if @issue.destroy
if issue_type == "2" && status_id != 5
post_to_chain("add", token, login)
end
normal_status(0, "删除成功")
else
normal_status(-1, "删除失败")
end
rescue => exception
Rails.logger.info("#########_______exception.message_________##########{exception.message}")
normal_status(-1, "删除失败")
else
end
end
def clean
#批量删除,暂时只能删除未悬赏的
issue_ids = params[:ids]
if issue_ids.present?
if Issue.where(id: issue_ids, issue_type: "1").destroy_all
normal_status(0, "删除成功")
else
normal_status(-1, "删除失败")
end
else
normal_status(-1, "请选择任务")
end
end
def series_update
update_hash = {}
update_hash.merge!(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present?
update_hash.merge!(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present?
# update_hash.merge!(status_id: params[:status_id]) if params[:status_id].present?
if params[:status_id].present?
status_id = params[:status_id].to_i
update_hash.merge!(status_id: status_id)
done_ratio = nil
case status_id
when 1
done_ratio = 0
when 3
done_ratio = 100
end
update_hash.merge!(done_ratio: done_ratio) if done_ratio
end
# update_hash = params[:issue]
issue_ids = params[:ids]
if issue_ids.present?
if update_hash.blank?
normal_status(-1, "请选择批量更新内容")
elsif Issue.where(id: issue_ids).update_all(update_hash)
normal_status(0, "批量更新成功")
else
normal_status(-1, "批量更新失败")
end
else
normal_status(-1, "请选择任务")
end
end
@ -317,6 +328,7 @@ class IssuesController < ApplicationController
def close_issue
type = params[:status_id].to_i || 5
if type == 5
message = "关闭"
old_message = "重新开启"
@ -327,18 +339,25 @@ class IssuesController < ApplicationController
if @issue.update_attribute(:status_id, type)
if type == 5
@issue&.project_trends&.update_all(action_type: "close")
@issue.issue_times.update_all(end_time: Time.now)
if @issue.issue_type.to_s == "2"
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
end
if @issue.issue_classify.to_s == "pull_request"
@issue&.pull_request&.update_attribute(:status, 2)
end
else
@issue&.project_trends&.update_all(action_type: "create")
if @issue.issue_classify.to_s == "pull_request"
@issue&.pull_request&.update_attribute(:status, 0)
end
end
if @issue.issue_classify == "issue"
close_message = "close_issue"
else
close_message = "close_pr"
end
@issue.custom_journal_detail(close_message,old_message, "#{message}")
@issue.custom_journal_detail(close_message,old_message, "#{message}", current_user&.id)
normal_status(0, message)
else
normal_status(-1, "操作失败")
@ -350,9 +369,9 @@ class IssuesController < ApplicationController
type = (params[:lock_type].to_i == 1)
if @issue.update_attribute(:is_lock, type)
if type
@issue.custom_journal_detail("lock_issue","", "因为#{params[:lock_reason].present? ? params[:lock_reason].to_s : "某种原因"}而锁定,并将对话限制为协作者")
@issue.custom_journal_detail("lock_issue","", "因为#{params[:lock_reason].present? ? params[:lock_reason].to_s : "某种原因"}而锁定,并将对话限制为协作者", current_user&.id)
else
@issue.custom_journal_detail("unlock_issue","", "解除锁定")
@issue.custom_journal_detail("unlock_issue","", "解除锁定", current_user&.id)
end
normal_status(0, "操作成功")
else
@ -365,11 +384,8 @@ class IssuesController < ApplicationController
end
private
def set_project_and_user
# @project = Project.find_by_identifier(params[:project_id]) || (Project.find params[:project_id]) || (Project.find params[:id])
def set_user
@user = @project&.owner
# normal_status(-1, "项目不存在") unless @project.present?
normal_status(-1, "用户不存在") unless @user.present?
end
def check_project_public
@ -388,7 +404,7 @@ class IssuesController < ApplicationController
end
def check_issue_permission
unless @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id)
unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id)))
normal_status(-1, "您没有权限")
end
end
@ -420,14 +436,56 @@ class IssuesController < ApplicationController
tracker_array
end
def get_branches
all_branches = []
get_all_branches = Gitea::Repository::BranchesService.new(@user, @project&.repository.try(:identifier)).call
if get_all_branches && get_all_branches.size > 0
get_all_branches.each do |b|
all_branches.push(b["name"])
end
def issue_send_params(params)
{
subject: params[:subject],
description: params[:description],
is_private: params[:is_private] || false,
assigned_to_id: params[:assigned_to_id],
tracker_id: params[:tracker_id],
status_id: params[:status_id],
priority_id: params[:priority_id],
fixed_version_id: params[:fixed_version_id],
start_date: params[:start_date].to_s.to_date || Time.current.to_date,
due_date: params[:due_date].to_s.to_date,
estimated_hours: params[:estimated_hours],
done_ratio: params[:done_ratio],
issue_type: params[:issue_type] || "1",
token: params[:token],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
closed_on: (params[:status_id].to_i == 5) ? Time.current : nil,
branch_name: params[:branch_name].to_s,
issue_classify: "issue",
author_id: current_user.id,
project_id: @project.id
}
end
def post_to_chain(type, amount,login)
change_params = {
type: type,
chain_params: {
amount: amount,
reponame: @project.try(:identifier),
username: login
}
}
PostChainJob.perform_later(change_params)
end
def check_token_enough
if params[:issue_type].to_s == "2" && (@issue.blank? || (@issue.present? && @issue.author_id == current_user.try(:id)))
return normal_status(-1, "悬赏的奖金必须大于0") if params[:token].to_i == 0
query_params = {
type: "query",
chain_params: {
reponame: @project.try(:identifier),
username: current_user.try(:login)
}
}
response = Gitea::Chain::ChainGetService.new(query_params).call
return normal_status(-1, "获取token失败请稍后重试") if response.status != 200
return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
end
all_branches
end
end

View File

@ -1,77 +0,0 @@
class ItemBanksController < ApplicationController
include PaginateHelper
before_action :require_login
before_action :certi_identity_auth, only: [:create, :edit, :update, :destroy, :set_public]
before_action :find_item, except: [:index, :create]
before_action :edit_auth, only: [:update, :destroy, :set_public]
before_action :identity_auth, only: [:index]
def index
items = ItemBankQuery.call(params)
@items_count = items.size
@items = paginate items.includes(:item_analysis, :user, :container)
exam = ExaminationBank.find_by(id: params[:exam_id]) if params[:exam_id].present?
exam_setting = ExaminationIntelligentSetting.find_by(id: params[:exam_setting_id]) if params[:exam_setting_id].present?
@item_basket_ids = if exam
exam.examination_items.pluck(:item_bank_id)
elsif exam_setting
exam_setting.item_baskets.pluck(:item_bank_id)
else
current_user.item_baskets.pluck(:item_bank_id)
end
end
def create
item = ItemBank.new(user: current_user)
ItemBanks::SaveItemService.call(item, form_params)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def edit
end
def update
ItemBanks::SaveItemService.call(@item, form_params)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def destroy
ActiveRecord::Base.transaction do
ApplyAction.where(container_type: "ItemBank", container_id: @item.id).destroy_all
if @item.item_type == "PROGRAM"
@item.container&.destroy!
else
@item.destroy!
end
render_ok
end
end
def set_public
tip_exception(-1, "该试题已公开") if @item.public?
tip_exception(-1, "请勿重复提交申请") if ApplyAction.where(container_id: @item.id, container_type: 'ItemBank', status: 0).exists?
ApplyAction.create!(container_id: @item.id, container_type: 'ItemBank', user_id: current_user.id)
# @item.update_attributes!(public: 1)
render_ok
end
private
def find_item
@item = ItemBank.find_by!(id: params[:id])
end
def edit_auth
current_user.admin_or_business? || @item.user == current_user
end
def form_params
params.permit(:discipline_id, :sub_discipline_id, :item_type, :difficulty, :name, :analysis, tag_discipline_id: [], choices: %i[choice_text is_answer])
end
end

View File

@ -1,96 +0,0 @@
class ItemBasketsController < ApplicationController
before_action :require_login
before_action :certi_identity_auth, only: [:create, :delete_item_type, :destroy, :set_score, :batch_set_score, :adjust_position]
before_action :validate_score, only: [:set_score, :batch_set_score]
helper_method :current_basket
def index
@item_baskets = basket_items
@single_questions = @item_baskets.where(item_type: "SINGLE")
@multiple_questions = @item_baskets.where(item_type: "MULTIPLE")
@judgement_questions = @item_baskets.where(item_type: "JUDGMENT")
@program_questions = @item_baskets.where(item_type: "PROGRAM")
end
def basket_list
@basket_count = current_user.item_baskets.group(:item_type).count
end
def create
ItemBaskets::SaveItemBasketService.call(current_user, create_params, exam_setting)
render_ok
rescue ApplicationService::Error => ex
render_error(ex.message)
end
def destroy
item = basket_items.find_by!(item_bank_id: params[:id])
ActiveRecord::Base.transaction do
basket_items.where(item_type: item.item_type).where("position > #{item.position}").update_all("position = position -1")
item.destroy!
end
render_ok
end
def delete_item_type
baskets = basket_items.where(item_type: params[:item_type])
baskets.destroy_all
render_ok
end
def set_score
current_basket.update_attributes!(score: params[:score])
@questions_score = basket_items.where(item_type: current_basket.item_type).pluck(:score).sum
@all_score = basket_items.pluck(:score).sum
end
def batch_set_score
basket_items.where(item_type: params[:item_type]).update_all(score: params[:score])
@questions_score = basket_items.where(item_type: params[:item_type]).pluck(:score).sum
@all_score = basket_items.pluck(:score).sum
end
def adjust_position
same_items = basket_items.where(item_type: current_basket.item_type)
max_position = same_items.size
tip_exception("position超出范围") unless params[:position].present? && params[:position].to_i <= max_position && params[:position].to_i >= 1
ActiveRecord::Base.transaction do
if params[:position].to_i > current_basket.position
same_items.where("position > #{current_basket.position} and position <= #{params[:position].to_i}").update_all("position=position-1")
current_basket.update_attributes!(position: params[:position])
elsif params[:position].to_i < current_basket.position
same_items.where("position < #{current_basket.position} and position >= #{params[:position].to_i}").update_all("position=position+1")
current_basket.update_attributes!(position: params[:position])
else
return normal_status(-1, "排序无变化")
end
end
render_ok
end
private
def create_params
params.permit(item_ids: [])
end
def exam_setting
@_exam_setting = ExaminationIntelligentSetting.find_by(id: params[:exam_setting_id])
end
def basket_items
@_items = params[:exam_setting_id] ? exam_setting.item_baskets : current_user.item_baskets
end
def current_basket
@_current_basket = ItemBasket.find_by!(id: params[:id])
tip_exception(403, "无权限编辑") unless current_user.admin_or_business? || @_current_basket.user_id.to_i == current_user.id ||
@_current_basket.examination_intelligent_setting&.user_id.to_i == current_user.id
@_current_basket
end
def validate_score
tip_exception("分值不能为空") unless params[:score].present?
tip_exception("分值需大于0") unless params[:score].to_f > 0
end
end

View File

@ -1,5 +1,5 @@
class JournalsController < ApplicationController
before_action :require_login
before_action :require_login, except: [:index, :get_children_journals]
before_action :set_issue
before_action :check_issue_permission
before_action :set_journal, only: [:destroy, :edit, :update]
@ -7,9 +7,13 @@ class JournalsController < ApplicationController
def index
@page = params[:page] || 1
@limit = params[:limit] || 10
journals = @issue.journals.journal_includes.order("created_on desc")
@journals_size = journals.size
@journals = journals.parent_journals.page(@page).per(@limit)
total_journals = @issue.journals.journal_includes
@jounals_total = total_journals.size
parent_journals = total_journals.parent_journals.order("created_on desc")
@journals = parent_journals.order("created_on desc").page(@page).per(@limit)
@journals_size = parent_journals.size
end
def create
@ -39,8 +43,8 @@ class JournalsController < ApplicationController
end
# @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal")
normal_status(0, "评论成功")
render :json => { status: 0, message: "评论成功", id: journal.id}
# normal_status(0, "评论成功")
else
normal_status(-1, "评论失败")
end
@ -49,6 +53,7 @@ class JournalsController < ApplicationController
def destroy
if @journal.destroy #如果有子评论,子评论删除吗?
Journal.children_journals(@journal.id).destroy_all
normal_status(0, "评论删除成功")
else
normal_status(-1, "评论删除失败")
@ -73,6 +78,14 @@ class JournalsController < ApplicationController
end
def get_children_journals
@page = params[:page] || 1
@limit = params[:limit] || 10
journals = Journal.children_journals(params[:id]).journal_includes.order("created_on desc")
@journals_size = journals.size
@children_journals = journals.page(@page).per(@limit)
end
private

View File

@ -1,5 +1,7 @@
class LicensesController < ApplicationController
def index
@licenses = License.search(params[:name]).without_content
#@licenses = License.search(params[:name]).
q = License.ransack(name_cont: params[:name])
@licenses = q.result(distinct: true)
end
end

View File

@ -1,13 +1,13 @@
class MembersController < ApplicationController
before_action :require_login
before_action :find_project_with_id
before_action :load_project
before_action :find_user_with_id, only: %i[create remove change_role]
before_action :operate!, except: %i[index]
before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role]
def create
interactor = Projects::AddMemberInteractor.call(current_user, @project, @user)
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
render_response(interactor)
rescue Exception => e
uid_logger_error(e.message)
@ -16,12 +16,17 @@ class MembersController < ApplicationController
def index
scope = @project.members.includes(:roles, user: :user_extension)
search = params[:search].to_s.downcase
role = params[:role].to_s
scope = scope.joins(:user).where("LOWER(concat(users.lastname, users.firstname, users.login, users.mail)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present?
scope = scope.joins(:roles).where("roles.name LIKE ?", "%#{role}%") if role.present?
@total_count = scope.size
@members = paginate(scope)
end
def remove
interactor = Projects::DeleteMemberInteractor.call(current_user, @project, @user)
interactor = Projects::DeleteMemberInteractor.call(@project.owner, @project, @user)
render_response(interactor)
rescue Exception => e
uid_logger_error(e.message)
@ -29,7 +34,7 @@ class MembersController < ApplicationController
end
def change_role
interactor = Projects::ChangeMemberRoleInteractor.call(current_user, @project, @user, params[:role])
interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role])
render_response(interactor)
rescue Exception => e
uid_logger_error(e.message)

View File

@ -1,199 +0,0 @@
class MemosController < ApplicationController
before_action :require_login, except: [:show, :index]
before_action :check_account, only: [:new, :create, :reply]
before_action :set_memo, only: [:show, :edit, :update, :destroy, :sticky_or_cancel, :hidden, :more_reply]
before_action :validate_memo_params, only: [:create, :update]
before_action :owner_or_admin, only: [:edit, :update, :destroy]
before_action :require_business, only: [:sticky_or_cancel, :hidden]
include ApplicationHelper
# GET /memos
# GET /memos.json
def index
@user = current_user
@memos = Memo.all
s_order = (params[:order] == "replies_count" ? "all_replies_count" : params[:order]) || "updated_at"
# @tidding_count = unviewed_tiddings(current_user) if current_user.present?
page = params[:page] || 1
limit = params[:limit] || 15
search = params[:search]
forum_id = params[:forum]
tag_repertoire_id = params[:tag_repertoire_id]
sql =
if forum_id
!search.blank? ? "forum_id = #{forum_id} and root_id is null and subject like '%#{search}%'" :
"forum_id = #{forum_id} and root_id is null"
elsif !search.blank?
"forum_id in(3, 5, 16) and root_id is null and subject like '%#{search}%'"
else
"forum_id in(3, 5, 16) and root_id is null"
end
if tag_repertoire_id
memo_ids = MemoTagRepertoire.where(tag_repertoire_id: tag_repertoire_id).pluck(:memo_id)
memo_ids = memo_ids ? memo_ids.join(",") : -1
sql += " and #{Memo.table_name}.id in(#{memo_ids})"
end
if params[:order] == "updated_at"
sql += " and all_replies_count != 0"
end
memos = Memo.field_for_list.where("#{sql}")
@memos_count = memos.length
@memos = memos.order("sticky = 1 desc, #{Memo.table_name}.#{s_order} desc").page(page).per(limit)
@memos = @memos.includes(:praise_treads, :tag_repertoires, author: :user_extension)
# @my_memos_count = Memo.user_posts(current_user.try(:id)).count
@tags_info = MemoTagRepertoire.find_by_sql("SELECT tag_repertoire_id, tr.name, count(*) cnt
FROM memo_tag_repertoires mtr join tag_repertoires tr on
tr.id = mtr.tag_repertoire_id group by tag_repertoire_id order by cnt desc,
tag_repertoire_id desc limit 9")
@hot_memos = Memo.field_for_recommend.posts.hot.includes(:tag_repertoires).limit(4)
@recommend_shixuns = DiscussesService.new.recommends
end
# GET /memos/1.json
def show
# tidding_count = unviewed_tiddings(current_user) if current_user
@user = current_user
@memo.update_column(:viewed_count, @memo.viewed_count+1)
@memos = @memo.reply_for_memo.includes(:praise_treads, author: :user_extension).order("created_at desc").limit(10)
@attachments = @memo.attachments
@recommend_shixuns = DiscussesService.new.recommends
end
# GET /memos/new
def new
@tag_list = TagRepertoire.field_for_list.order("name asc")
end
# GET /memos/1/edit
def edit
@tag_list = TagRepertoire.field_for_list.order("name asc")
@memo_tags = @memo.tag_repertoires.field_for_list
@attachments = @memo.attachments
end
# POST /memos.json
def create
ActiveRecord::Base.transaction do
begin
@memo = Memo.new(memo_params)
@memo.author = current_user
@memo.save!
Attachment.associate_container(params[:attachment_ids], @memo.id, @memo.class.name)
params[:tags].each do |tag|
MemoTagRepertoire.create!(memo_id: @memo.id, tag_repertoire_id: tag)
end
render :json => {memo_id: @memo.id, status: 0, message: "帖子创建成功"}
rescue Exception => e
tip_exception("帖子创建失败,原因:#{e}")
raise ActiveRecord::Rollback
end
end
end
# PATCH/PUT /memos/1.json
def update
ActiveRecord::Base.transaction do
begin
@memo.update_attributes!(memo_params)
Attachment.associate_container(params[:attachment_ids], @memo.id, @memo.class.name)
@memo.memo_tag_repertoires.destroy_all
params[:tags].each do |tag|
MemoTagRepertoire.create!(memo_id: @memo.id, tag_repertoire_id: tag)
end
normal_status("帖子更新成功")
rescue Exception => e
tip_exception("帖子更新失败,原因:#{e}")
raise ActiveRecord::Rollback
end
end
end
# DELETE /memos/1
# DELETE /memos/1.json
def destroy
@memo.destroy
normal_status("删除成功")
end
def sticky_or_cancel
tip_exception("只能对主贴进行置顶操作") unless @memo.parent_id.nil?
begin
@memo.update_attributes!(sticky: !@memo.sticky)
normal_status("更新成功")
rescue Exception => e
tip_exception("更新失败,原因:#{e}")
raise ActiveRecord::Rollback
end
end
def hidden
tip_exception("不能对主贴进行隐藏操作") if @memo.parent_id.nil?
begin
@memo.update_attributes!(hidden: @memo.hidden == 0 ? 1 : 0)
normal_status("更新成功")
rescue Exception => e
tip_exception("更新失败,原因:#{e}")
raise ActiveRecord::Rollback
end
end
def reply
tip_exception("parent_id不能为空") if params[:parent_id].blank?
tip_exception("content不能为空") if params[:content].blank?
tip_exception("内容不能超过2000字符") if params[:content].length > 2000
ActiveRecord::Base.transaction do
begin
memo = Memo.find_by!(id: params[:parent_id])
@reply = Memo.new
@reply.content = params[:content]
@reply.author = current_user
@reply.forum_id = memo.forum_id
@reply.subject = memo.subject
@reply.root_id = memo.root_id || memo.id
memo.children << @reply
m = Memo.find_by!(id: @reply.root_id)
m.update_attributes!(all_replies_count: m.all_replies_count + 1)
rescue Exception => e
tip_exception("回复失败,原因:#{e}")
raise ActiveRecord::Rollback
end
end
end
def more_reply
@user = current_user
page = params[:page] || 2
limit = params[:limit] || 10
offset = (page.to_i - 1) * limit
@memos_count = Memo.where(parent_id: @memo.id).count
@memos = Memo.limit(limit).where(parent_id: @memo.id).includes(:author, :praise_treads).order("created_at desc").offset(offset)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_memo
@memo = Memo.find(params[:id])
end
def owner_or_admin
tip_exception(403, "无权限操作") unless @memo.author == current_user || current_user.admin? || current_user.business?
end
# Never trust parameters from the scary internet, only allow the white list through.
def memo_params
params.require(:memo).permit(:subject, :content, :forum_id)
end
def validate_memo_params
tip_exception("话题名称不能为空") if params[:subject].blank?
tip_exception("话题内容不能为空") if params[:content].blank?
tip_exception("话题类型不能为空") if params[:forum_id].blank?
tip_exception("技术标签不能为空") if params[:forum_id].to_i == 5 && params[:tags].blank?
end
end

View File

@ -1,225 +0,0 @@
class MessagesController < ApplicationController
include MessagesHelper
SORT_TYPE = %w[time hot]
before_action :require_login, :check_auth, only: %i[create update sticky_top bulk_delete create destroy bulk_send bulk_move bulk_public]
before_action :find_board, only: [:create, :index, :bulk_delete, :bulk_move, :bulk_send, :bulk_public]
before_action :find_message, only: [:update, :destroy, :sticky_top, :reply_list, :destroy, :reply]
before_action :validate_delete_params, only: %i[bulk_delete bulk_public]
before_action :message_validate_create_params, only: :create
before_action :validate_update_params, only: :update
before_action :validate_sort_type, only: :index
before_action :validate_send_message_to_course_params, only: :bulk_send
before_action :validate_move_params, only: :bulk_move
def index
@page = params[:page] || 1
@page_size = params[:page_size] || 15
sort = params[:sort].to_i == 1 ? 'asc' : 'desc'
sort_type = params[:sort_type] || 'time'
if @board.parent_id == 0
messages = Message.where(board_id: @board.course.boards.pluck(:id))
else
messages = @board.messages
end
messages = messages.root_nodes.by_keywords(params[:search])
messages = messages.reorder('(sticky = 1) DESC') # 置顶
messages =
case sort_type
when 'time' then messages.order("created_on #{sort}")
when 'hot' then messages.order("descendants_count #{sort}")
else messages.order("created_on #{sort}")
end
messages = messages.includes(:author, :board)
@messages = Kaminari.paginate_array(messages).page(@page).per(@page_size)
ids = @messages.map(&:id)
@praises_count_map = Message.where(root_id: ids).group(:root_id).sum(:praises_count)
end
def reply_list
@page = params[:page] || 1
@page_size = params[:page_size] || 10
@current_user = current_user || nil
@messages = @message.children.preload_messages.includes(:message_detail, :praise_treads)
# @messages = @messages.ordered(sort: 1) unless @message.parent_id.nil?
@user_course_identity = current_user.course_identity(@message.board.course)
case @user_course_identity
when 5, 6, 7
@messages = @messages.visible
end
@messages = @messages.reorder("messages.created_on desc")
@messages = @messages.page(@page).per(@page_size)
end
def reply
return normal_status(-1, "回复内容不能为空") if params[:content].blank?
return normal_status(-1, "回复内容不能超过2000字符") if params[:content].length > 2000
@reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id,
author: current_user, parent: @message,
message_detail_attributes: {
content: params[:content]
})
end
def sticky_top
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course)
@message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1)
end
def bulk_delete
ActiveRecord::Base.transaction do
begin
@messages = @board.messages.by_ids(params[:ids])
@messages.destroy_all
rescue Exception => e
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def new
@message = Message.new
end
def show
@message = Message.includes(:attachments, :message_detail,
:children, :author => :user_extension,
:board => [{course: :board_course_modules}])
.find_by_id params[:id]
return normal_status(-2, "ID为#{params[:id]}的帖子不存在") if @message.nil?
@attachment_size = @message.attachments.size
@message.update_visits
@current_user = current_user
end
def update
return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course)
begin
board = @message.board&.course&.boards.find_by!(id: params[:select_board_id])
email_notify = @message.email_notify ? 1 : @message.board&.course.email_notify && params[:email_notify]
send_email = !@message.email_notify && email_notify
h = {is_md: true, email_notify: email_notify, board_id: board&.id}
m_params = message_params.merge(h)
@message.update_attributes(m_params)
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
@message.update_content(params[:content])
notify_course_students(@message, @message.board&.course) if send_email
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def create
return normal_status(403, "您没有权限进行该操作") unless current_user.admin_or_business? || current_user.member_of_course?(@board.course)
begin
@message = Message.new(message_params)
@message.author = current_user
@message.board_id = params[:select_board_id]
@message.message_detail_attributes = {content: params[:content]}
@message.email_notify = @board.course.email_notify && params[:email_notify] ? 1 : 0
@message.save!
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
if @board.course.email_notify && params[:email_notify]
notify_course_students @message, @board.course
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def destroy
begin
return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@message.board.course) >= 5 || @message.author != current_user
@message.destroy!
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def bulk_send
return normal_status(403) unless current_user.teacher_or_admin?(@board.course)
ids = params[:ids]
course_ids = params[:to_course_ids]
begin
ids.each do |id|
@message = Message.find_by_id id
if @message.try(:parent_id).nil? # TODO 暂时只支持目录下的跟节点发送
course_ids.each do |course_id|
course = Course.find course_id
new_message = Message.create!(board: course.course_board,
subject: @message.subject,
author: current_user,
message_detail_attributes: {
content: @message.try(:message_detail).try(:content)
}
)
@message.copy_attachments_to_new_message(new_message, current_user)
end
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def bulk_move
# 课堂的目录之间移动,有子栏目的才显示此项
return normal_status(403) unless current_user.teacher_of_course?(@board.course)
Message.bulk_move_to_other_board(params[:ids], params[:to_board_id])
end
def bulk_public
@messages = @board.messages.root_nodes.by_ids Array(params[:ids])
@messages.update_all(is_public: true)
end
private
def validate_sort_type
normal_status(2, "参数sort_type暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
def find_message
begin
@message = Message.find params[:id]
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
end
def message_params
params.require(:message).permit(:subject, :sticky)
end
def notify_course_students message, course
course.students.includes(:user).each do |student|
UserMailer.course_message_email(student&.user&.mail, message.id).deliver_later if student&.user&.mail
end
end
end

View File

@ -0,0 +1,35 @@
class Oauth::EducoderController < Oauth::BaseController
def bind
begin
login = params[:login]
mail = params[:mail] || nil
callback_url = params[:callback_url]
token = params[:token]
::OauthEducoderForm.new({login: login, token: token, callback_url: callback_url}).validate!
open_user= OpenUsers::Educoder.find_by(uid: login) || OpenUsers::Educoder.find_by(uid: mail)
if open_user.present? && open_user.user.present? && open_user.user.email_binded?
Rails.logger.info "######## open_user exist and open_user.user exsit and email is binded ok"
successful_authentication(open_user.user)
redirect_to callback_url
else
Rails.logger.info "######## open user not exits"
user = User.find_by(login: login) || User.find_by(mail: mail)
if user.is_a?(User) && !user.is_a?(AnonymousUser)
OpenUsers::Educoder.create!(user: user, uid: login)
successful_authentication(user)
redirect_to callback_url
else
redirect_to oauth_register_path(login: login, mail: mail, callback_url: callback_url)
end
end
rescue WechatOauth::Error => ex
render_error(ex.message)
end
end
end

View File

@ -1,4 +1,6 @@
class OauthController < ApplicationController
layout "oauth_register", only: [:register]
DEFAULT_PASSWORD = "a12345678"
TOKEN_CALL_BACK = "/oauth/get_token_callback"
USER_INFO = "/oauth/userinfo"
@ -51,4 +53,35 @@ class OauthController < ApplicationController
def get_token_callback
end
def register
end
def auto_register
login = params[:login]
email = params[:mail]
password = params[:password]
callback_url = params[:callback_url]
platform = params[:plathform] || 'educoder'
if User.where(mail: email).exists?
render json: { email_exist: '该邮箱已使用过' }
else
result = autologin_register(login, email, password, platform)
logger.info "[Oauth educoer] =====#{result}"
if result[:message].blank?
logger.info "[Oauth educoer] ====auto_register success"
user = User.find result[:user][:id]
successful_authentication(user)
OpenUsers::Educoder.create!(user: user, uid: user.login)
render json: { callback_url: callback_url }
# redirect_to callback_url
else
logger.info "[Oauth educoer] ====auto_register failed."
render :action => "auto_register"
end
end
end
end

View File

@ -1,138 +0,0 @@
class PartnersController < ApplicationController
skip_before_action :check_sign
include Base::PaginateHelper
include Admins::RenderHelper
layout 'college'
before_action :require_login, :check_partner_present!, :check_permission!
before_action :check_admin_manager_group_permission!, except: [:customers]
helper_method :current_partner, :manager_permission?
def customers
customers = CustomerQuery.call(current_partner, current_user, params)
@customers = paginate(customers.includes(:school))
load_customer_extra_statistic_data
end
def partner_manager_groups
@manager_groups = current_partner.partner_manager_groups.includes(users: :user_extension).to_a
end
def manager_group
name = params[:manager_group_name].to_s.strip
if params[:manager_group_id].present?
# 重命名
@manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
return render_error('不能修改管理者权限组名称') if @manager_group.admin?
@manager_group.update!(name: name)
else
# 新建
@manager_group = current_partner.partner_manager_groups.create!(name: name)
end
end
def remove_manager_group
manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
return render_error('不能删除管理者权限组') if manager_group.admin?
manager_group.destroy!
render_delete_success
end
def partner_managers
user_ids = Array.wrap(params[:user_ids])
@manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
ActiveRecord::Base.transaction do
User.where(id: user_ids).pluck(:id).each do |user_id|
next if current_partner.partner_managers.exists?(partner_manager_group: @manager_group, user_id: user_id)
current_partner.partner_managers.create!(partner_manager_group: @manager_group, user_id: user_id)
end
end
@manager_group.reload
end
def remove_partner_manager
partner_manager = current_partner.partner_managers.find(params[:manager_id])
return render_error('不能删除自己') if partner_manager.user_id == current_user.id && partner_manager.partner_manager_group.admin?
partner_manager.destroy!
render_delete_success
end
def customer_manager_group
customer = current_partner.customers.find(params[:customer_id])
if params[:manager_group_id].present?
manager_group = current_partner.partner_manager_groups.find(params[:manager_group_id])
customer.update!(partner_manager_group: manager_group)
else
customer.update!(partner_manager_group_id: nil)
end
render_ok
end
private
def current_partner
@_current_partner ||= Partner.find(params[:id].presence || params[:partner_id])
end
def check_partner_present!
return if current_partner.present?
redirect_to '/404'
end
def manager_permission?
admin_or_business? || current_user.partner_managers.exists?(partner_id: current_partner.id)
end
def check_permission!
return if manager_permission?
redirect_to '/403'
end
def check_admin_manager_group_permission!
return if admin_or_business?
return if current_partner.admin_partner_manager_group.partner_managers.exists?(user: current_user)
render_forbidden
end
def load_customer_extra_statistic_data
school_ids = @customers.map(&:school_id)
teacher_map = UserExtension.where(school_id: school_ids, identity: 0).group(:school_id).count
student_map = UserExtension.where(school_id: school_ids, identity: 1).group(:school_id).count
course_map = Course.where(school_id: school_ids, is_delete: 0).where.not(id: 1309).group(:school_id).count
shixun_map = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id')
.where(user_extensions: { school_id: school_ids }).group('user_extensions.school_id').count
shixun_report_map = StudentWork.where(work_status: [1, 2]).where('myshixun_id != 0')
.joins('left join user_extensions on user_extensions.user_id = student_works.user_id')
.where(user_extensions: { school_id: school_ids })
.group('user_extensions.school_id').count
course_time_map = Course.where(school_id: school_ids, is_delete: 0)
.where.not(id: 1309).group(:school_id).maximum(:updated_at)
@customers.each do |customer|
customer._extra_data = {
teacher_count: teacher_map[customer.school_id],
student_count: student_map[customer.school_id],
course_count: course_map[customer.school_id],
shixun_count: shixun_map[customer.school_id],
shixun_report_count: shixun_report_map[customer.school_id],
course_time: course_time_map[customer.school_id]
}
end
end
end

View File

@ -11,7 +11,7 @@ class PraiseTreadController < ApplicationController
begin
return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
current_user.like!(@project)
render_ok
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -23,7 +23,7 @@ class PraiseTreadController < ApplicationController
begin
return normal_status(2, "你还没有点过赞噢") unless current_user.liked?(@project)
current_user.unlike!(@project)
render_ok
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -39,4 +39,9 @@ class PraiseTreadController < ApplicationController
tip_exception(e.message)
end
private
def render_result
end
end

View File

@ -1,11 +1,13 @@
class ProjectCategoriesController < ApplicationController
def index
@project_categories = ProjectCategory.search(params[:name]).without_content
# @project_categories = ProjectCategory.search(params[:name]).without_content
q = ProjectCategory.ransack(name_cont: params[:name])
@project_categories = q.result(distinct: true)
end
def group_list
@category_group_list =
Project.visible.joins(:project_category).group(:project_category_id)
.select("project_category_id, count(*) AS projects_count, project_categories.name")
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
# projects = Project.no_anomory_projects.visible
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
end
end

View File

@ -1,5 +1,7 @@
class ProjectLanguagesController < ApplicationController
def index
@project_languages = ProjectLanguage.search(params[:name]).without_content
#@project_languages = ProjectLanguage.search(params[:name]).
q = ProjectLanguage.ransack(name_cont: params[:name])
@project_languages = q.result(distinct: true)
end
end

View File

@ -1,5 +1,5 @@
class ProjectTrendsController < ApplicationController
before_action :find_project
before_action :load_repository
before_action :check_project_public
def index
@ -44,4 +44,4 @@ class ProjectTrendsController < ApplicationController
normal_status(-1, "您没有权限")
end
end
end
end

View File

@ -1,5 +1,7 @@
class Projects::BaseController < ApplicationController
include PaginateHelper
before_action :require_login, :check_auth
before_action :load_project
before_action :load_repository
end

View File

@ -1,20 +1,34 @@
class ProjectsController < ApplicationController
include ApplicationHelper
include OperateProjectAbilityAble
before_action :require_login, except: %i[index branches group_type_list]
before_action :find_project_with_id, only: %i[show branches update destroy]
include ProjectsHelper
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about]
before_action :load_project, except: %i[index group_type_list migrate create recommend]
before_action :authorizate_user_can_edit_project!, only: %i[update]
before_action :project_public?, only: %i[fork_users praise_users watch_users]
def index
scope = Projects::ListQuery.call(params)
@total_count = scope.size
@projects = paginate(scope)
# @projects = kaminari_paginate(scope)
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, owner: :user_extension)
category_id = params[:category_id]
@total_count =
if category_id.blank?
ps = ProjectStatistic.first
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
else
cate = ProjectCategory.find_by(id: category_id)
cate&.projects_count || 0
end
end
def create
ActiveRecord::Base.transaction do
Projects::CreateForm.new(project_params).validate!
@project = Projects::CreateService.new(current_user, project_params).call
end
rescue Exception => e
uid_logger_error(e.message)
@ -22,30 +36,48 @@ class ProjectsController < ApplicationController
end
def migrate
ActiveRecord::Base.transaction do
Projects::MigrateForm.new(mirror_params).validate!
@project = Projects::MigrateService.new(current_user, mirror_params).call
end
Projects::MigrateForm.new(mirror_params).validate!
@project = Projects::MigrateService.new(current_user, mirror_params).call
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def branches
@branches = Gitea::Repository::BranchesService.new(@project.owner, @project.identifier).call
@branches = @project.forge? ? Gitea::Repository::Branches::ListService.new(@owner, @project.identifier).call : []
end
def group_type_list
@project_group_list = Project.visible.group(:project_type).select('project_type, count(*) AS projects_count')
project_statics = ProjectStatistic.first
@project_statics_list = [
{
project_type: 'common',
name: '开源托管项目',
projects_count: project_statics&.common_projects_count || 0
},
{
project_type: 'mirror',
name: '开源镜像项目',
projects_count: project_statics&.mirror_projects_count || 0
}
]
# projects = Project.no_anomory_projects.visible
# @project_group_list = projects.group(:project_type).size
end
def update
ActiveRecord::Base.transaction do
# Projects::CreateForm.new(project_params).validate!
private = params[:private]
gitea_params = {
private: private,
default_branch: params[:default_branch]
}
if [true, false].include? private
new_project_params = project_params.merge(is_public: !private)
Gitea::Repository::UpdateService.new(@project.owner, @project.repository.identifier, {private: private}).call
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
@project.repository.update_column(:hidden, private)
end
@project.update_attributes!(new_project_params)
@ -73,6 +105,61 @@ class ProjectsController < ApplicationController
tip_exception(e.message)
end
def watch_users
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
@watchers_count = watchers.size
@watchers = paginate(watchers)
end
def praise_users
praises = @project.praise_treads.includes(:user).order("praise_treads.created_at desc").distinct
@praises_count = praises.size
@praises = paginate(praises)
end
def fork_users
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
@forks_count = fork_users.size
@fork_users = paginate(fork_users)
end
def simple
json_response(@project, current_user)
end
def recommend
@projects = Project.recommend.includes(:repository, :project_category, owner: :user_extension).limit(5)
end
def about
@project_detail = @project.project_detail
@attachments = Array(@project_detail&.attachments) if request.get?
ActiveRecord::Base.transaction do
if request.post?
require_login
authorizate_user_can_edit_project!
unless @project_detail.present?
@project_detail = ProjectDetail.new(
content: params[:content],
project_id: @project.id)
else
@project_detail.content = params[:content]
end
if @project_detail.save!
attachment_ids = Array(params[:attachment_ids])
logger.info "=============> #{Array(params[:attachment_ids])}"
@attachments = Attachment.where(id: attachment_ids)
@attachments.update_all(
container_id: @project_detail.id,
container_type: @project_detail.model_name.name,
author_id: current_user.id,
description: "")
end
end
end
end
private
def project_params
params.permit(:user_id, :name, :description, :repository_name,
@ -80,7 +167,18 @@ class ProjectsController < ApplicationController
end
def mirror_params
params.permit(:user_id, :name, :description, :repository_name,
:project_category_id, :project_language_id, :clone_addr, :private)
params.permit(:user_id, :name, :description, :repository_name, :is_mirror, :auth_username,
:auth_password, :project_category_id, :project_language_id, :clone_addr, :private)
end
def project_public?
return if @project.is_public?
if current_user
return if current_user.admin? || @project.member?(current_user.id)
render_forbidden('你没有权限访问.')
else
render_unauthorized('你还未登录.')
end
end
end

View File

@ -1,76 +1,55 @@
class PullRequestsController < ApplicationController
before_action :require_login
before_action :find_project
before_action :set_repository
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge]
before_action :require_login, except: [:index, :show, :files, :commits]
before_action :load_repository
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
before_action :load_pull_request, only: [:files, :commits]
include TagChosenHelper
include ApplicationHelper
def index
# @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取
issues = @project.issues.issue_pull_request.includes(:user,:tracker, :priority, :version, :issue_status, :journals, :issue_times)
issues = @project.issues.issue_pull_request.issue_index_includes.includes(pull_request: :user)
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@all_issues_size = issues.size
@open_issues_size = issues.where.not(status_id: 5).size
@close_issues_size = issues.where(status_id: 5).size
@assign_to_me_size = issues.where(assigned_to_id: current_user&.id).size
@my_published_size = issues.where(author_id: current_user&.id).size
@open_issues_size = issues.joins(:pull_request).where(pull_requests: {status: 0}).size
@close_issues_size = issues.joins(:pull_request).where(pull_requests: {status: 2}).size
@merged_issues_size = issues.joins(:pull_request).where(pull_requests: {status: 1}).size
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
status_type = params[:status_type] || "1" #issue状态的选择
search_name = params[:search].to_s
start_time = params[:start_date]
end_time = params[:due_date]
if status_type.to_s == "1" #表示开启中的
issues = issues.where.not(status_id: 5)
elsif status_type.to_s == "2" #表示关闭中的
issues = issues.where(status_id: 5)
end
if search_name.present?
issues = issues.where("subject like ?", "%#{search_name}%")
end
if start_time&.present? || end_time&.present?
issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date)
end
issues = issues.where(author_id: params[:author_id]) if params[:author_id].present?
issues = issues.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present? && params[:assigned_to_id].to_s != "all"
issues = issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present?
issues = issues.where(status_id: params[:status_id]) if params[:status_id].present?
issues = issues.where(priority_id: params[:priority_id]) if params[:priority_id].present?
issues = issues.where(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present? && params[:fixed_version_id].to_s != "all"
issues = issues.where(done_ratio: params[:done_ratio].to_i) if params[:done_ratio].present?
issues = issues.where(issue_type: params[:issue_type]) if params[:issue_type].present?
issues = issues.joins(:issue_tags).where(issue_tags: {id: params[:issue_tag_id].to_i}) if params[:issue_tag_id].present?
order_type = params[:order_type] || "desc" #或者"asc"
order_name = params[:order_name] || "created_on" #或者"updated_on"
@page = params[:page]
@limit = params[:limit] || 15
@issues = issues.order("#{order_name} #{order_type}")
@issues_size = issues.size
@issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit)
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "PullRequest")
@issues_size = scopes.size
@issues = paginate(scopes)
end
def new
@all_branches = []
get_all_branches = Gitea::Repository::BranchesService.new(@user, @repository.try(:identifier)).call
if get_all_branches && get_all_branches.size > 0
get_all_branches.each do |b|
@all_branches.push(b["name"])
end
@all_branches = PullRequests::BranchesService.new(@owner, @project).call
@is_fork = @project.forked_from_project_id.present?
@projects_names = [{
project_user_login: @owner.try(:login),
project_name: "#{@owner.try(:show_real_name)}/#{@repository.try(:identifier)}",
project_id: @project.identifier,
id: @project.id
}]
@merge_projects = @projects_names
fork_project = @project.fork_project if @is_fork
if fork_project.present?
@merge_projects.push({
project_user_login: fork_project.owner.try(:login),
project_name: "#{fork_project.owner.try(:show_real_name)}/#{fork_project.repository.try(:identifier)}",
project_id: fork_project.identifier,
id: fork_project.id
})
end
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
@project_versions = @project.versions&.select(:id,:name, :status).as_json
@project_members = @project.members_user_infos
end
def get_branches
branch_result = PullRequests::BranchesService.new(@owner, @project).call
render json: branch_result
# return json: branch_result
end
def create
if params[:title].nil?
normal_status(-1, "名称不能为空")
elsif params[:issue_tag_ids].nil?
@ -78,55 +57,29 @@ class PullRequestsController < ApplicationController
else
ActiveRecord::Base.transaction do
begin
local_params = {
title: params[:title], #标题
body: params[:body], #内容
head: params[:head], #源分支
base: params[:base], #目标分支
milestone: 0, #里程碑,未与本地的里程碑关联
}
requests_params = local_params.merge({
assignee: current_user.try(:login),
assignees: ["#{params[:assigned_login].to_s}"],
labels: params[:issue_tag_ids],
due_date: Time.now
})
issue_params = {
author_id: current_user.id,
project_id: @project.id,
subject: params[:title],
description: params[:body],
assigned_to_id: params[:assigned_to_id],
fixed_version_id: params[:fixed_version_id],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
issue_classify: "pull_request",
issue_type: params[:issue_type] || "1",
tracker_id: 2,
status_id: 1,
priority_id: 1
}
pull_issue = Issue.new(issue_params)
merge_params
pull_issue = Issue.new(@issue_params)
if pull_issue.save!
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: pull_issue.id))
pr_params = {
user_id: current_user.try(:id),
project_id: @project.id,
issue_id: pull_issue.id,
fork_project_id: params[:fork_project_id],
is_original: params[:is_original],
files_count: params[:files_count] || 0,
commits_count: params[:commits_count] || 0
}
local_requests = PullRequest.new(@local_params.merge(pr_params))
if local_requests.save
gitea_request = Gitea::PullRequest::CreateService.new(current_user, @repository.try(:identifier), requests_params).call
remote_pr_params = @local_params
remote_pr_params = remote_pr_params.merge(head: "#{params[:merge_user_login]}:#{params[:head]}").compact if local_requests.is_original && params[:merge_user_login]
gitea_request = Gitea::PullRequest::CreateService.call(current_user.try(:gitea_token), @project.owner, @repository.try(:identifier), remote_pr_params.except(:milestone))
if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"])
if params[:issue_tag_ids].present?
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: pull_issue.id, issue_tag_id: tag)
end
end
if params[:attachment_ids].present?
params[:attachment_ids].each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
unless attachment.blank?
attachment.container = pull_issue
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
end
if params[:assigned_to_id].present?
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
@ -136,8 +89,9 @@ class PullRequestsController < ApplicationController
end
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
if params[:title].to_s.include?("WIP:")
pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。")
pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。", current_user&.id)
end
# render :json => { status: 0, message: "PullRequest创建成功", id: pull_issue.id}
normal_status(0, "PullRequest创建成功")
else
normal_status(-1, "PullRequest创建失败")
@ -155,8 +109,9 @@ class PullRequestsController < ApplicationController
end
def edit
@issue_chosen = issue_left_chosen(@project, @issue.id)
@issue_attachments = @issue.attachments
@fork_project_user_name = @project&.fork_project&.owner.try(:show_real_name)
@fork_project_user = @project&.fork_project&.owner.try(:login)
@fork_project_identifier = @project&.fork_project&.repository.try(:identifier)
end
def update
@ -167,25 +122,7 @@ class PullRequestsController < ApplicationController
else
ActiveRecord::Base.transaction do
begin
local_params = {
title: params[:title], #标题
body: params[:body], #内容
head: params[:head], #源分支
base: params[:base], #目标分支
milestone: 0, #里程碑,未与本地的里程碑关联
}
requests_params = local_params.merge({
assignee: current_user.try(:login),
assignees: ["#{params[:assigned_login].to_s}"],
labels: params[:issue_tag_ids]
})
issue_params = {
subject: params[:title],
description: params[:body],
assigned_to_id: params[:assigned_to_id].to_s,
fixed_version_id: params[:fixed_version_id],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
}
merge_params
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
@issue&.issue_tags_relates&.destroy_all
@ -194,26 +131,10 @@ class PullRequestsController < ApplicationController
end
end
if @issue.update_attributes(issue_params)
if @pull_request.update_attributes(local_params)
gitea_request = Gitea::PullRequest::UpdateService.new(current_user, @repository.try(:identifier), requests_params, @pull_request.try(:gpid)).call
if @issue.update_attributes(@issue_params)
if @pull_request.update_attributes(@local_params.compact)
gitea_request = Gitea::PullRequest::UpdateService.new(@project.owner, @repository.try(:identifier), @requests_params, @pull_request.try(:gpid)).call
if gitea_request
issue_files = params[:attachment_ids]
change_files = false
issue_file_ids = []
if issue_files.present?
change_files = true
issue_files.each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
unless attachment.blank?
attachment.container = @issue
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
end
if params[:issue_tag_ids].present?
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
@ -222,7 +143,6 @@ class PullRequestsController < ApplicationController
if params[:status_id].to_i == 5
@issue.issue_times.update_all(end_time: Time.now)
end
@issue.create_journal_detail(change_files, issue_files, issue_file_ids)
normal_status(0, "PullRequest更新成功")
else
normal_status(-1, "PullRequest更新失败")
@ -240,39 +160,47 @@ class PullRequestsController < ApplicationController
end
def refuse_merge
ActiveRecord::Base.transaction do
begin
@pull_request.update(status: 2)
@pull_request.issue.update(status_id: 5)
normal_status(1, "已拒绝")
rescue => e
normal_status(-1, e.message)
raise ActiveRecord::Rollback
end
end
end
def create_merge_infos
get_relatived
end
def show
@user_permission = current_user.present? && (!@issue.is_lock || @project.member?(current_user) || current_user.admin? || @issue.user == current_user)
@issue_attachments = @issue.attachments
@issue_user = @issue.user
@issue_assign_to = @issue.get_assign_user
@join_users = join_users(@issue)
#总耗时
cost_time(@issue)
#被依赖
@be_depended_issues_array = be_depended_issues(@issue)
#依赖于
depended_issues(@issue)
end
def pr_merge
return render_forbidden("你没有权限操作.") if @project.reporter?(current_user)
if params[:do].blank?
normal_status(-1, "请选择合并方式")
else
ActiveRecord::Base.transaction do
begin
requests_params = {
do: params[:do],
Do: params[:do],
MergeMessageField: params[:body],
MergeTitleField: params[:title]
}
merge_pr = Gitea::PullRequest::MergeService.new(current_user, @repository.try(:identifier), @pull_request.try(:gpid), requests_params).call
merge_pr = Gitea::PullRequest::MergeService.call(current_user.gitea_token, @project.owner.login,
@repository.try(:identifier), @pull_request.try(:gpid), requests_params)
if @pull_request.update_attribute(:status, 1) && merge_pr[:status].to_i == 200
# @pull_request.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "merge")
@pull_request&.project_trends&.update_all(action_type: "close")
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并")
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
normal_status(1, "合并成功")
else
normal_status(-1, "合并失败")
@ -285,73 +213,21 @@ class PullRequestsController < ApplicationController
end
end
#评审
def check_merge
notes = params[:content]
pull_request_status = params[:status]
if notes.blank?
normal_status(-1, "评论内容不能为空")
else
if @pull_request.status > 0
normal_status(-1, "已合并,不能评审")
else
if pull_request_status.to_i == 1
message = "评审通过:"
elsif pull_request_status.to_i == 2
message = "评审请求变更:"
else
message = ""
end
journal_params = {
journalized_id: @issue.id ,
journalized_type: "Issue",
user_id: current_user.id ,
notes: message + notes.to_s.strip
}
journal = Journal.new journal_params
if journal.save
if pull_request_status.present?
@pull_request.update_attribute(:status, pull_request_status.to_i)
end
if pull_request_status.to_i == 1
requests_params = {
do: "merge",
MergeMessageField: notes,
MergeTitleField: "Merge PullRequest ##{@pull_request.gpid}"
}
merge_pr = Gitea::PullRequest::MergeService.new(current_user, @repository.try(:identifier), @pull_request.try(:gpid), requests_params).call
if merge_pr
@pull_request&.project_trends&.update_all(action_type: "close")
# @pull_request.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "merge")
@issue.custom_journal_detail("merge", "", "该合并请求已被合并")
normal_status(1, "评审成功")
else
normal_status(-1, "评审失败")
end
end
normal_status(0, "评审成功")
else
normal_status(-1, "评审失败")
end
end
end
end
def check_can_merge
target_head = params[:head] #源分支
target_base = params[:base] #目标分支
is_original = params[:is_original]
if target_head.blank? || target_base.blank?
normal_status(-1, "请选择分支")
elsif target_head === target_base
normal_status(-1, "分支内容相同,无需创建合并请求")
normal_status(-2, "请选择分支")
elsif target_head === target_base && !is_original
normal_status(-2, "分支内容相同,无需创建合并请求")
else
can_merge = @project&.pull_requests.where(user_id: current_user&.id, head: target_head, base: target_base, status: 0)
can_merge = @project&.pull_requests.where(head: target_head, base: target_base, status: 0, is_original: is_original, fork_project_id: params[:fork_project_id])
if can_merge.present?
render json: {
status: -2,
message: "在这些分支之间的合并请求已存在",
pull_request_id: can_merge.first.id,
pull_request_name: can_merge.first.try(:title)
message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>",
}
else
normal_status(0, "可以合并")
@ -360,15 +236,19 @@ class PullRequestsController < ApplicationController
end
private
def files
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid)
# render json: @files_result
end
def set_repository
# @project = Project.find_by_identifier! params[:id]
@repository = @project.repository
@user = @project.owner
# normal_status(-1, "项目不存在") unless @project.present?
normal_status(-1, "仓库不存在") unless @repository.present?
normal_status(-1, "用户不存在") unless @user.present?
def commits
@commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid)
# render json: @commits_result
end
private
def load_pull_request
@pull_request = PullRequest.find params[:id]
end
def find_pull_request
@ -380,4 +260,41 @@ class PullRequestsController < ApplicationController
normal_status(-1, "您没有权限")
end
end
end
def get_relatived
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
@project_versions = @project.versions&.select(:id,:name, :status).as_json
@project_members = @project.members_user_infos
@project_priories = IssuePriority&.select(:id,:name, :position).as_json
end
def merge_params
@local_params = {
title: params[:title], #标题
body: params[:body], #内容
head: params[:head], #源分支
base: params[:base], #目标分支
milestone: 0, #里程碑,未与本地的里程碑关联
}
@requests_params = @local_params.merge({
assignee: current_user.try(:login),
assignees: ["#{params[:assigned_login].to_s}"],
labels: params[:issue_tag_ids],
due_date: Time.now
})
@issue_params = {
author_id: current_user.id,
project_id: @project.id,
subject: params[:title],
description: params[:body],
assigned_to_id: params[:assigned_to_id],
fixed_version_id: params[:fixed_version_id],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
priority_id: params[:priority_id] || "2",
issue_classify: "pull_request",
issue_type: params[:issue_type] || "1",
tracker_id: 2,
status_id: 1,
}
end
end

View File

@ -1,5 +0,0 @@
class RepertoiresController < ApplicationController
def index
render_ok(repertoires: Repertoire.select(:id, :name).order(:created_at).as_json)
end
end

View File

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

View File

@ -1,4 +1,6 @@
class SettingsController < ApplicationController
def show
@old_projects_url = nil
@old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged?
end
end

View File

@ -1,896 +0,0 @@
class StudentWorksController < ApplicationController
include HomeworkCommonsHelper
include StudentWorksHelper
before_action :require_login, :check_auth
before_action :find_homework, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project, :delete_work]
before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des,
:adjust_score, :show, :adjust_score, :supply_attachments, :revise_attachment,
:comment_list, :add_score, :add_score_reply, :destroy_score, :appeal_anonymous_score,
:deal_appeal_score, :cancel_appeal, :edit, :update, :export_shixun_work_report,
:shixun_work_comment, :destroy_work_comment]
before_action :user_course_identity
before_action :allow_add_score, only: [:add_score]
before_action :homework_publish
before_action :teacher_allowed, only: [:adjust_score, :adjust_review_score, :deal_appeal_score, :shixun_work_comment,
:destroy_work_comment]
before_action :course_student, only: [:new, :commit_des, :update_des, :create, :edit, :update, :search_member_list, :relate_project,
:cancel_relate_project, :relate_project, :delete_work]
before_action :my_work, only: [:commit_des, :update_des, :edit, :update, :revise_attachment, :appeal_anonymous_score,
:cancel_appeal]
before_action :edit_duration, only: [:edit, :update, :delete_work]
before_action :end_or_late, only: [:new, :create, :search_member_list, :commit_des, :update_des]
before_action :require_score_id, only: [:destroy_score, :add_score_reply, :appeal_anonymous_score, :deal_appeal_score, :cancel_appeal]
before_action :is_evaluation, :open_work, only: [:show, :supply_attachments]
def new
uid_logger("#######new current_user : 1111")
@current_user = current_user
uid_logger("#######new current_user : #{@current_user.id}")
if @homework.homework_type == "group" && @homework.homework_detail_group.try(:base_on_project)
work = @homework.student_works.find_by(user_id: @current_user.id)
if work.present? && (work.work_status != 0 || work.project_id == 0)
normal_status(403, "")
end
end
end
# 搜索课堂学生
def search_member_list
# 统一设置的作业取所有学生,否则取已发布的分班学生
students = @homework.unified_setting? ? @course.students : @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id))
if !params[:search].blank?
@members = students.joins(user: :user_extension).where("course_members.user_id != #{current_user.id} and (concat(users.lastname, users.firstname)
like ? or user_extensions.student_id like ?)", "%#{params[:search]}%", "%#{params[:search]}%")
else
# 没有搜索条件时搜索课堂所有未提交的学生
user_ids = @homework.student_works.where("work_status = 0").pluck(:user_id) - [current_user.id]
@members = students.where(user_id: user_ids)
end
page = params[:page] ? params[:page].to_i : 1
limit = params[:limit] ? params[:limit].to_i : 10
# todo user_extension
@members = @members.page(page).per(limit).includes(:course_group, user: :user_extension)
end
def delete_work
ActiveRecord::Base.transaction do
begin
work = @homework.student_works.find_by!(user_id: params[:user_id])
tip_exception("只有组长才能删除组员") if work.commit_user_id != current_user.id
work.update_attributes!(description: nil, project_id: 0,
late_penalty: 0, work_status: 0,
commit_time: nil, update_time: nil, group_id: 0,
commit_user_id: nil, final_score: nil, work_score: nil, teacher_score: nil, teaching_asistant_score: nil)
work.attachments.destroy_all
work.tidings.destroy_all
normal_status("删除成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
end
end
end
def create
student_work = @homework.student_works.find_or_create_by(user_id: current_user.id)
tip_exception("作业不可重复提交") if student_work.work_status != 0
update_check student_work
student_ids = [current_user.id]
ActiveRecord::Base.transaction do
begin
student_work.description = params[:description]
student_work.commit_time = Time.now
student_work.update_time = Time.now
student_work.commit_user_id = current_user.id
student_work.update_user_id = current_user.id
student_work.group_id = @homework.homework_type == "group" ? @homework.max_group_id : 0
#提交作品时,计算是否迟交
homework_setting = @homework.homework_group_setting(current_user.id)
student_work.late_penalty = homework_setting.end_time < Time.now ? @homework.late_penalty : 0
student_work.work_status = homework_setting.end_time < Time.now ? 2 : 1
if student_work.save!
Attachment.associate_container(params[:attachment_ids], student_work.id, student_work.class)
if @homework.homework_type == "group"
members = (params[:user_ids] || []).collect(&:to_i) - [current_user.id]
members = @course.students.pluck(:user_id) & members
student_ids += members
for i in 0 .. members.count-1
stu_work = @homework.student_works.find_or_initialize_by(user_id: members[i].to_i)
stu_work.update_attributes!(user_id: members[i].to_i, description: student_work.description,
homework_common_id: @homework.id, project_id: student_work.project_id,
late_penalty: student_work.late_penalty, work_status: student_work.work_status,
commit_time: Time.now, update_time: Time.now, group_id: student_work.group_id,
commit_user_id: current_user.id, update_user_id: current_user.id)
stu_work.save!
student_work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
stu_work.attachments << att
end
end
end
@homework.update_column(:updated_at, Time.now)
# todo 更新对应的作业课堂动态
# update_course_activity(@taskhomework.class,@task.id)
@work_id = student_work.id
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
SubmitStudentWorkNotifyJob.perform_later(@homework.id, student_ids)
end
def edit
@current_user = current_user
if @homework.homework_type == "group"
# todo user_extension
@commit_user_id = @work.commit_user_id
@work_members = @course.students.where(user_id: @homework.student_works.where(group_id: @work.group_id).pluck(:user_id)).
order("course_members.user_id=#{@work.commit_user_id} desc").includes(:course_group, user: :user_extension)
end
end
def update
update_check @work
student_ids = []
ActiveRecord::Base.transaction do
begin
@work.description = params[:description]
@work.update_time = Time.now
@work.update_user_id = current_user.id
# @work.commit_user_id = current_user.id
if @work.save!
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class)
#如果学生作品被打分后修改,应该给老师提示
student_ids << @work.user_id if @work.scored?
if @homework.homework_type == "group"
student_works = @homework.student_works.where("group_id = #{@work.group_id} and user_id != #{@work.user_id}")
work_user_ids = student_works.pluck(:user_id)
params_user_ids = (params[:user_ids] || []).collect(&:to_i) - [@work.user_id]
params_user_ids = @course.students.pluck(:user_id) & params_user_ids
# 原成员更新描述、更新时间以及附件
@homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work|
# work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id)
work.update_attributes!(update_time: Time.now, description: @work.description, update_user_id: current_user.id)
work.attachments.destroy_all
@work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
work.attachments << att
end
student_ids << work.user_id if work.scored?
end
# 删除的成员
delete_user_ids = work_user_ids - params_user_ids
@homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids).each do |work|
work.attachments.destroy_all
# work.student_works_scores.destroy_all
work.tidings.destroy_all
end
@homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids).
update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil,
final_score: nil, teacher_score: nil, student_score: nil, teaching_asistant_score: nil,
work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil, update_user_id: nil)
# 新增加的成员
(params_user_ids - work_user_ids).each do |user_id|
stu_work = @homework.student_works.find_or_initialize_by(user_id: user_id)
stu_work.update_attributes!(user_id: user_id, description: @work.description, homework_common_id: @homework.id,
project_id: @work.project_id, late_penalty: @work.late_penalty,
work_status: @work.work_status, commit_time: Time.now, update_time: Time.now,
group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id)
@work.attachments.each do |attachment|
att = attachment.copy
att.author_id = attachment.author_id
stu_work.attachments << att
end
student_ids << user_id
end
end
normal_status(0,"更新成功")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
ResubmitStudentWorkNotifyJob.perform_later(@homework.id, student_ids) if student_ids.present?
end
end
def show
@current_user = current_user
@work_members = @homework.homework_type != "group" ? [] : @homework.student_works.where.not(user_id: @work.user_id).
where(group_id: @work.group_id).includes(:user)
@attachments = @work.attachments.where("attachtype != 7 or attachtype is null")
end
# 判断项目是否已有其他作品关联上了
def check_project
tip_exception("项目id不能为空") if params[:project_id].blank?
work = @homework.student_works.find_by_project_id(params[:project_id])
@is_relate = work.present?
@relate_user = work.present? ? work.user.real_name : ""
end
def relate_project
tip_exception("项目id不能为空") if params[:project_id].blank?
ActiveRecord::Base.transaction do
begin
# 判断项目是否存在且当前用户是项目管理员
project = Project.find_by_id(params[:project_id])
member = Member.find_by_project_id_and_user_id(project.try(:id), current_user.id)
if project.present? && member.present? && member.member_roles.take.try(:role_id) == 3
work = @homework.student_works.find_or_create_by(user_id: current_user.id)
if work.work_status == 0 && work.project_id == 0
work.update_attributes!(project_id: project.id, update_time: Time.now)
# 将老师加入项目
project_member = project.members.find_by_user_id(@homework.user_id)
if project_member.present?
project_member.member_roles.take.update_attributes!(role_id: 3) if project_member.member_roles.take.present?
else
member = Member.create!(user_id: @homework.user_id, project_id: project.id)
member.member_roles << MemberRole.new(role_id: 3)
Tiding.create(user_id: @homework.user_id, trigger_user_id: current_user.id, container_id: project.id,
container_type: 'ManagerJoinProject', belong_container_id: project.id,
belong_container_type: "Project", tiding_type: "System", extra: 3)
end
normal_status(0,"关联成功")
else
tip_exception("不能重复关联项目")
end
else
tip_exception("该项目不存在")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def cancel_relate_project
work = @homework.student_works.find_by_user_id_and_work_status(current_user.id, 0)
if work.present? && work.project.present?
ActiveRecord::Base.transaction do
begin
member = work.project.members.find_by_user_id(@homework.user_id)
member.destroy if member.present?
Tiding.where(user_id: @homework.user_id, trigger_user_id: current_user.id, container_id: work.project.id,
container_type: 'ManagerJoinProject').destroy_all
work.update_attributes!(project_id: 0)
normal_status(0,"取消关联成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
else
tip_exception("无法取消关联")
end
end
def supply_attachments
@revise_attachments = @work.attachments.where(attachtype: 7)
@last_atta = @revise_attachments.last
end
def revise_attachment
tip_exception("不在补交阶段内") unless @homework.late_duration
tip_exception("附件参数有误") if params[:attachment_ids].blank? || !params[:attachment_ids].is_a?(Array)
tip_exception("补交附件原因不能为空") if params[:description].blank?
ActiveRecord::Base.transaction do
begin
# 补交作业附件不覆盖之前上传的附件
# revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last
# if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}'
# and score is not null").count == 0
# revise_attachment.destroy
# end
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7)
revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "StudentWork").last
revise_attachment.update_attributes!(description: params[:description]) if revise_attachment.present?
@work.update_attributes!(update_time: Time.now)
# 补交附件时给评阅过作品的教师、助教发消息
unless @work.student_works_scores.where.not(score: nil).where(reviewer_role: [1, 2]).pluck(:user_id).uniq.blank?
ResubmitStudentWorkNotifyJob.perform_later(@homework.id, [current_user.id])
end
normal_status(0, "提交成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def comment_list
@current_user = current_user
@last_comment = @work.student_works_scores.where(user_id: @current_user.id).last
# todo user_extension
@comment_scores = (@user_course_identity < Course::STUDENT || current_user == @work.user) ?
@work.student_works_scores.reorder("created_at desc") :
@work.student_works_scores.where(user_id: current_user.id).reorder("created_at desc")
@comment_scores = @comment_scores.includes(:student_works_scores_appeal, :attachments, journals_for_messages: :user, user: :user_extension)
end
# 给作品评分
def add_score
tip_exception("该学生的分数已经过调整,不能再评阅") if @work.ultimate_score
tip_exception("分数和评语不能都为空") if params[:score].blank? && params[:comment].blank?
tip_exception("分数不能超过0-100") if params[:score] && (params[:score].to_f < 0 || params[:score].to_f > 100)
ActiveRecord::Base.transaction do
begin
# 没传score则取上次评分成绩
reviewer_role = @user_course_identity == Course::STUDENT ? 3 : @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1
new_score = StudentWorksScore.new
score = StudentWorksScore.where(user_id: current_user.id, student_work_id: @work.id, reviewer_role: reviewer_role).last
new_score.score = params[:score].blank? ? score.try(:score) : params[:score].to_f
new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != ""
new_score.user_id = current_user.id
new_score.student_work_id = @work.id
# 如果作品是未提交的状态则更新为已提交
if @user_course_identity < Course::STUDENT && !new_score.score.nil? && @work.work_status == 0
@work.update_attributes!(work_status: 1, commit_time: Time.now)
# 分组作业更新分组id
@work.update_attributes!(group_id: @homework.max_group_id) if @homework.homework_type == "group"
end
new_score.reviewer_role = reviewer_role
if new_score.save!
Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class)
# 该用户的历史评阅无效
score.update_column('is_invalid', true) if score.present? && score.score.present?
Tiding.create(user_id: @work.user_id, trigger_user_id: User.current.id, container_id: new_score.id,
container_type: "StudentWorksScore", parent_container_id: @work.id,
parent_container_type: "HomeworkCommon", belong_container_id: @homework.course_id,
belong_container_type: "Course", viewed: 0, tiding_type: new_score.reviewer_role == 3 ? "System" : "HomeworkCommon", extra: new_score.reviewer_role)
case new_score.reviewer_role
when 1 #教师评分:最后一个教师评分为最终评分
@work.teacher_score = new_score.score
if @homework.homework_type == "group" && params[:same_score]
add_score_to_member @work, @homework, new_score
end
when 2 #教辅评分 教辅评分显示平均分
# 助教评分:普通模式则是平均分,复审模式则是最新评分
if @homework.homework_detail_manual.ta_mode == 1
@work.teaching_asistant_score = new_score.ta_score @work.id
else
@work.teaching_asistant_score = new_score.score
end
if @homework.homework_type == "group" && params[:same_score]
add_score_to_member @work, @homework, new_score
end
when 3 #学生评分 学生评分显示平均分
# 匿评分
@work.student_score = new_score.stu_score(@work.id)
if @homework.homework_type == "group" && new_score.score.present?
add_score_to_member @work, @homework, new_score
end
current_user.student_works_scores.where(student_work_id: @work.id, reviewer_role: 3, appeal_status: 1).update_all(appeal_status: 5)
end
@homework.update_column('updated_at', Time.now)
# update_course_activity(@homework.class,@homework.id)
@work.save!
normal_status(0,"提交成功")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# 实训作品的提交总结
def commit_des
@current_user = current_user
end
# 实训作品的总结
def update_des
@work.update_attributes!(des_params)
tip_exception(0, "提交成功")
end
# 实训作品弹框
def shixun_work
@myshixun = @work.myshixun
if @myshixun.present?
@current_user = current_user
@work_user = @work.user
@shixun = @homework.shixuns.take
else
tip_exception("作品还未提交")
end
end
# 实训报告
def shixun_work_report
@user = @work.user
@shixun = @homework.shixuns.take
# 提示: 这里如果includes outputs表的话 sum(:evaluate_count)会出现错误
@games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun
@challenges = @shixun.challenges if @shixun
@comment = @work.shixun_work_comments.find_by(challenge_id: 0)
# 用户最大评测次数
if @games
@user_evaluate_count = @games.pluck(:evaluate_count).sum
@games = @games.includes(:challenge, :game_codes, :outputs)
else
@user_evaluate_count = 0
end
# 图形效率图的数据
@echart_data = student_efficiency(@homework, @work) if @work.myshixun
end
# 实训作品的评阅
def shixun_work_comment
tip_exception("请至少输入一个评阅") if params[:comment].blank? && params[:hidden_comment].blank?
ActiveRecord::Base.transaction do
challenge = @homework.shixuns.first&.challenges.find_by(id: params[:challenge_id]) unless params[:challenge_id].blank?
if challenge.present?
@comment = @work.shixun_work_comments.find_by(challenge_id: challenge.id) ||
ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: challenge.id)
else
@comment = @work.shixun_work_comments.find_by(challenge_id: 0) ||
ShixunWorkComment.new(student_work_id: @work.id, user_id: current_user.id, challenge_id: 0)
end
@comment.comment = params[:comment]
@comment.hidden_comment = params[:hidden_comment]
@comment.save!
if @work.work_status == 0
@work.update_attributes!(work_status: 1, commit_time: @homework.end_time, update_time: Time.now, work_score: 0, final_score: 0)
end
end
end
# 删除实训作品评阅
def destroy_work_comment
ActiveRecord::Base.transaction do
# tip_exception("visible_comment参数有误") if params[:visible_comment].nil?
comment = @work.shixun_work_comments.find_by!(id: params[:comment_id])
comment.destroy!
# params[:visible_comment] ? comment.comment = nil : comment.hidden_comment = nil
# if comment.comment.nil? && comment.hidden_comment.nil?
# comment.destroy!
# else
# comment.save!
# end
normal_status("删除成功")
end
end
def export_shixun_work_report
@user = @work.user
@shixun = @homework.shixuns.take
@games = @work.myshixun.games.includes(:challenge, :game_codes, :outputs) if @work.myshixun
@challenges = @shixun.challenges if @shixun
# 用户最大评测次数
@user_evaluate_count = @games.pluck(:evaluate_count).sum if @games
# 图形效率图的数据
@echart_data = student_efficiency(@homework, @work)
@myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id }
@myself_consume = @echart_data[:consume_list].find { |item| item.last == @user.id }
filename_ = "#{@homework.course&.user_group_name(@work.user_id)}_#{@user&.student_id}_#{@user&.real_name}_#{@shixun&.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf"
filename = filename_.strip.tr("+/", "-_")
stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
if params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
set_export_cookies
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# 作品调分
def adjust_score
tip_exception("成绩不能为空") if params[:score].blank?
tip_exception("成绩不能小于零") if params[:score].to_f < 0
tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100
tip_exception("调分原因不能超过100个字符") if params[:comment].present? && params[:comment].length > 100
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效
@work.student_works_scores.where.not(score: nil).update_all(is_invalid: 1)
reviewer_role = @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1
new_score = StudentWorksScore.new(student_work_id: @work.id, score: params[:score].to_f, comment: "使用调分功能调整了作业最终成绩:#{params[:comment]}",
user_id: current_user.id, reviewer_role: reviewer_role, is_ultimate: 1)
new_score.save!
# 如果作品是未提交的状态则更新为已提交
if @work.work_status == 0
@work.work_status = 1
@work.commit_time = Time.now
@work.compelete_status = 1 if @homework.homework_type == "practice"
# 分组作业更新分组id
@work.group_id = @homework.max_group_id if @homework.homework_type == "group"
end
@work.ultimate_score = true
@work.work_score = params[:score].to_f
@work.save!
Tiding.create!(user_id: @work.user_id, trigger_user_id: current_user.id, container_id: new_score.id,
container_type: "AdjustScore", parent_container_id: @homework.id,
parent_container_type: "HomeworkCommon", belong_container_id: @course.id,
belong_container_type: 'Course', tiding_type: "HomeworkCommon")
normal_status(0,"调分成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
#添加评分的回复
def add_score_reply
tip_exception("回复内容不能为空") if params[:comment].blank?
ActiveRecord::Base.transaction do
begin
score = @work.student_works_scores.find_by!(id: params[:score_id])
jour = score.journals_for_messages.new(user_id: current_user.id, notes: params[:comment], reply_id: score.user_id)
jour.save!
normal_status(0,"回复成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
# 删除教师/教辅的评分记录
def destroy_score
score = @work.student_works_scores.find_by(id: params[:score_id])
tip_exception("该评阅记录不存在") unless score.present?
tip_exception("该评阅记录不能删除") unless score.allow_delete(current_user)
begin
score.destroy
normal_status(0,"删除成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
# 对学生匿评进行申诉
def appeal_anonymous_score
tip_exception("申诉原因不能为空") if params[:comment].blank?
score = @work.student_works_scores.find_by(id: params[:score_id].to_i)
tip_exception("无法申诉") unless score.present? && @homework.appeal_duration &&
score.reviewer_role == 3 && score.appeal_status == 0
score_appeal = nil
ActiveRecord::Base.transaction do
begin
score.update_attributes!(appeal_status: 1)
score_appeal = StudentWorksScoresAppeal.create!(user_id: current_user.id, student_works_score_id: score.id,
comment: params[:comment], appeal_status: 1)
normal_status(0,"提交成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
# 提交后给老师和助教、匿评人发消息
StudentWorkScoreAppealNotifyJob.perform_later(@course.id, score_appeal.id, current_user.id)
end
# 撤销申诉
def cancel_appeal
score = @work.student_works_scores.find_by(id: params[:score_id].to_i)
if score.present? && score.appeal_status == 1
ActiveRecord::Base.transaction do
begin
score.update_attributes!(appeal_status: 2)
score_appeal = score.student_works_scores_appeal
score_appeal.update_attributes!(appeal_status: 2)
score_appeal.tidings.destroy_all
normal_status(0,"撤销成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
else
tip_exception("无法撤销")
end
end
# status 3 接受 4 拒绝
def deal_appeal_score
tip_exception("缺少status参数") if params[:status].blank?
tip_exception("status值不合要求") unless params[:status].to_i == 3 || params[:status].to_i == 4
score = @work.student_works_scores.find_by(id: params[:score_id].to_i)
if score.present? && score.appeal_status == 1
ActiveRecord::Base.transaction do
begin
# 更新appeal_status的值
score.update_attributes!(appeal_status: params[:status].to_i)
score_appeal = score.student_works_scores_appeal
score_appeal.update_attributes!(appeal_status: params[:status].to_i)
score_appeal.tidings.update_all(status: 1)
if params[:status].to_i == 3
# 申诉成功后该评分失效
score.update_attributes!(is_invalid: 1)
# 申诉成功后 扣匿评学生的违规匿评扣分
sw = @homework.student_works.find_by(user_id: score.user_id)
sw.update_attributes!(appeal_penalty: @homework.homework_detail_manual.appeal_penalty + sw.appeal_penalty) if sw.present?
# 申诉成功 重新计算申诉者的匿评分
if @work.student_works_scores.where("reviewer_role = 3 AND appeal_status != 3").count > 0
@work.student_score = score.stu_score(@work.id)
else
@work.student_score = nil
end
@work.save!
end
# todo tiding
Tiding.create(user_id: score_appeal.user_id, trigger_user_id: current_user.id, container_id: score_appeal.id,
container_type: "StudentWorksScoresAppeal", parent_container_id: @work.id,
parent_container_type: 'UserAppealResult', belong_container_id: @course.id,
belong_container_type: "Course", viewed: 0, status: params[:status].to_i == 3 ? 1 : 2,
tiding_type: "HomeworkCommon")
Tiding.create(user_id: score.user_id, trigger_user_id: current_user.id, container_id: score_appeal.id,
container_type: "StudentWorksScoresAppeal", parent_container_id: @work.id,
parent_container_type: 'AppealResult', belong_container_id: @course.id, belong_container_type: "Course",
viewed: 0, status: params[:status].to_i == 3 ? 1 : 2, tiding_type: "HomeworkCommon")
normal_status(0,"提交成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
else
tip_exception("该申诉不存在")
end
end
# 查重作品调分
def adjust_review_score
tip_exception("缺少type参数") if params[:type].blank? || !["review", "report"].include?(params[:type])
if params[:type] == "review" && (params[:score].blank? || params[:challenge_id].blank? || params[:code_rate].blank? || params[:copy_user_id].blank?)
tip_exception("参数错误score和challenge_id和code_rate和copy_user_id不能为空")
elsif params[:type] == "report" && (params[:score].blank? || params[:challenge_id].blank?)
tip_exception("参数错误score和challenge_id不能为空")
end
challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id])
if challenge_setting
challenge = challenge_setting&.challenge
tip_exception("不能小于零") if params[:score].to_i < 0
tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting && challenge_setting.score < params[:score].to_i
ActiveRecord::Base.transaction do
begin
if params[:type] == "review"
copy_user = User.find params[:copy_user_id]
comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%"
else
comment = "根据实训报告中最终提交的代码调整第#{challenge.position}关分数"
end
challenge_score = @work.challenge_work_scores.create!(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score],
comment: comment)
challenge_score.create_tiding current_user.id
if @work.work_status != 0 && @work.myshixun
games = @work.myshixun.games.where(challenge_id: @homework.homework_challenge_settings.pluck(:challenge_id))
HomeworksService.new.update_myshixun_work_score @work, @work.myshixun, games, @homework, @homework.homework_challenge_settings
else
update_none_commit_work @work, @homework
end
rescue Exception => e
uid_logger(e.message)
tip_exception("调分失败")
raise ActiveRecord::Rollback
end
end
else
tip_exception("该关卡不记分")
end
end
private
def find_homework
begin
@homework = HomeworkCommon.find params[:homework_common_id]
@course = @homework.course
rescue Exception => e
uid_logger_error("##########{e.message}")
missing_template
end
end
def find_work
begin
@work = StudentWork.find params[:id]
@homework = @work.homework_common
@course = @homework.course
rescue Exception => e
uid_logger_error("##########{e.message}")
missing_template
end
end
def homework_public
tip_exception(403,"没有操作权限") unless @user_course_identity <= Course::STUDENT ||
(@course.is_public == 1 && @homework.is_public)
end
def course_student
uid_logger("#########course-student")
tip_exception(403,"没有操作权限") if @user_course_identity != Course::STUDENT
end
def my_work
tip_exception(403,"没有操作权限") if @work.user_id != current_user.id || @work.work_status == 0
end
def edit_duration
tip_exception("已过了修改时间") if @homework.end_time && @homework.end_time < Time.now
end
def end_or_late
tip_exception("不在提交/更新阶段") if @homework.end_or_late
end
def des_params
tip_exception("description参数不能为空") if params[:description].blank?
params.require(:student_work).permit(:description)
end
def require_score_id
tip_exception("score_id参数不能为空") if params[:score_id].blank?
end
# 是否匿评阶段
def is_evaluation
@is_author = @work.user_id == current_user.id
@is_evaluation = @user_course_identity == Course::STUDENT && !@is_author && @homework.anonymous_comment &&
[3, 4].include?(@homework.homework_detail_manual.comment_status)
end
# 作品是否公开
def open_work
tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @homework.work_public || @is_evaluation)
end
def allow_add_score
# 老师始终有评阅权限,匿评阶段内,学生对分配给该学生的作品有评阅权限
tip_exception(403, "没有权限") unless allow_score(@homework, @user_course_identity, current_user.id, @work)
end
def update_check work
tip_exception("作品描述不能为空") if params[:description].blank?
if @homework.homework_type == "group"
tip_exception("小组成员不能为空") if params[:user_ids].blank?
tip_exception("小组成员人数不合要求") if params[:user_ids].length > @homework.homework_detail_group.max_num ||
params[:user_ids].length < @homework.homework_detail_group.min_num
tip_exception("请先关联项目") if @homework.homework_detail_group.base_on_project && work.project_id == 0
end
end
def add_score_to_member student_work, homework, new_score
student_works = homework.student_works.where("group_id = #{student_work.group_id} and id != #{student_work.id} and ultimate_score = 0")
student_works.each do |st_work|
st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score,
reviewer_role: new_score.reviewer_role, comment: new_score.comment)
score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id, reviewer_role: new_score.reviewer_role).last
# 该用户的历史评阅无效
score.update_column('is_invalid', true) if score.present? && score.score.present?
st_work.student_works_scores << st_score
if new_score.reviewer_role == 1
st_work.teacher_score = new_score.score if new_score.score.present?
elsif new_score.reviewer_role == 2
if homework.homework_detail_manual.ta_mode == 1
st_work.teaching_asistant_score = new_score.ta_score st_work.id
else
st_work.teaching_asistant_score = new_score.score if new_score.score.present?
end
else
st_work.student_score = student_work.student_score
end
st_work.save!
Tiding.create(user_id: st_work.user_id, trigger_user_id: current_user.id, container_id: st_score.id,
container_type: "StudentWorksScore", parent_container_id: st_work.id, parent_container_type: "StudentWork",
belong_container_id: homework.course_id, belong_container_type: "Course", viewed: 0,
tiding_type: "HomeworkCommon", extra: new_score.reviewer_role)
new_score.attachments.each do |attachment|
att = attachment.copy
att.author_id = st_score.user_id
st_score.attachments << att
end
end
end
def update_none_commit_work work, homework
if work.work_status == 0
work.work_status = 1
work.compelete_status = 1
work.commit_time = homework.end_time
work.update_time = Time.now
end
final_score = 0
homework.homework_challenge_settings.each do |cha_setting|
adjust_score = work.challenge_work_scores.select{|work_score| work_score.challenge_id == cha_setting.challenge_id}.last
final_score += adjust_score.score if adjust_score.present?
end
work.final_score = final_score
work.work_score = final_score
work.save!
end
end

View File

@ -0,0 +1,334 @@
class SyncForgeController < ApplicationController
# before_action :check_token
def sync_range_projects
sync_counts = params[:sync_count] || 10
projects = Project.includes(:project_score, :repository)
.where(is_public: true)
.where.not(identifier: ["educoder","trustieforge", "gitlab", "rGDBbQmOK", "socialforge"])
.joins(:project_score).order("project_scores.changeset_num desc").limit(sync_counts.to_i)
projects.each do | project |
SyncProjectMilitaryJob.perform_later(project, project.repository, project.project_score)
end
end
# def create
# ActiveRecord::Base.transaction do
# params.permit!
# sync_params = params[:sync_params]
# project_user = User.where(login: sync_params[:owner_login])&.first
# #以前已同步的项目,那么肯定存在仓库
# SyncLog.sync_log("=================begin_to_sync_forge: project_identifier: #{sync_params[:identifier]}========")
# user_projects = Project.where(user_id: project_user.id)
# if user_projects.where(id: sync_params[:id], identifier: sync_params[:identifier]).present?
# has_project = true
# project = user_projects.where(id: sync_params[:id], identifier: sync_params[:identifier])&.first
# elsif user_projects.where(id: sync_params[:id]).present?
# has_project = true
# project = user_projects.where(id: sync_params[:id])&.first
# elsif user_projects.where(identifier: sync_params[:identifier]).present?
# has_project = true
# project = user_projects.where(identifier: sync_params[:identifier])&.first
# else
# has_project = false
# end
# if has_project
# SyncLog.sync_log("=================begin_to_update_project========")
# check_sync_project(project, sync_params)
# else #新建项目
# SyncLog.sync_log("=================begin_to_create_new_project========")
# project_params = {
# repository_name: sync_params[:identifier],
# user_id: project_user.id,
# private: !sync_params[:is_public],
# name: sync_params[:name]
# }
# project = Projects::CreateService.new(project_user, project_params).call
# if project.present?
# if sync_params[:project_score].present?
# sync_params.permit!
# score_params = sync_params[:project_score].merge(project_id: project.id)
# new_project_score = ProjectScore.create(score_params)
# SyncLog.sync_log("=================new_project_score:#{new_project_score.try(:id)}========")
# end
# SyncRepositoryJob.perform_later(sync_params[:owner_login], sync_params[:identifier], sync_params[:repository], get_sudomain) if sync_params[:repository].present?
# check_new_project(project, sync_params)
# else
# SyncLog.sync_project_log("=============new_project_create_failed, trustie_project_id==:#{params[:sync_params][:id]}")
# end
# end
# end
# rescue Exception => e
# SyncLog.sync_project_log("=============sync_has_errors:==#{e.message}, project_id==:#{params[:sync_params][:id]}")
# end
# def sync_users
# params.permit!
# sync_params = params[:sync_params]
# users_params = sync_params[:users]
# users_params.each do |u|
# if User.exists?(login: u[:user_params][:login])
# SyncLog.sync_log("=================sync_to_user_been_exists====#{u[:user_params][:login]}")
# else
# # new_user = User.new(u[:user_params])
# if u[:user_params][:mail].blank?
# u_mail = "#{u[:user_params][:login]}@example.com"
# else
# u_mail = u[:user_params][:mail]
# end
# new_user = User.new(u[:user_params].merge(mail: u_mail))
# username = new_user.login
# password = "12345678"
# # if new_user.save!
# # SyncLog.sync_log("=================sync_to_user_success==#{new_user.login}")
# # else
# # SyncLog.sync_log("=================sync_to_user_failed,user_login==#{new_user.login}")
# # end
# ActiveRecord::Base.transaction do
# interactor = Gitea::RegisterInteractor.call({username: username, email: new_user.mail, password: password})
# if interactor.success?
# gitea_user = interactor.result
# result = Gitea::User::GenerateTokenService.new(username, password).call
# new_user.gitea_token = result['sha1']
# new_user.gitea_uid = gitea_user['id']
# if new_user.save!
# UserExtension.create!(u[:user_extensions][:user_extensions].merge(user_id: new_user.id)) if u[:user_extensions].present? && u[:user_extensions][:user_extensions].present?
# else
# SyncLog.sync_log("=================sync_to_user_failed,user_login==#{new_user.login}")
# end
# else
# SyncLog.sync_log("=============sync_to_user_failed,user_login====#{new_user.login}")
# SyncLog.sync_log("=================sync_to_user_failed,user_login====#{new_user.login}")
# end
# end
# end
# end
# # normal_status(1, "completed_sync")
# rescue Exception => e
# SyncLog.sync_log("=================sync_user_failed====#{e}")
# end
# private
# def check_sync_project(project,sync_params)
# begin
# gitea_main = "https://www.trustie.net/"
# # if request.subdomain === 'testforgeplus'
# # gitea_main = "https://ucloudtest.trustie.net/"
# # end
# SyncLog.sync_log("----begin_to_check_sync_project----project_id:#{project.id}---------------")
# change_project_score(project, sync_params[:project_score], sync_params[:repository]) if sync_params[:repository].present? #更新project_score
# change_project_issues(project, sync_params[:issues],project.id, gitea_main)
# change_project_members(project, sync_params[:members],gitea_main)
# change_project_versions(project, sync_params[:project_versions],gitea_main)
# change_project_watchers(project, sync_params[:project_watchers],gitea_main)
# change_project_praises(project, sync_params[:praise_trends],gitea_main)
# rescue => e
# SyncLog.sync_log("=========check_sync_project_errors:#{e}===================")
# end
# end
# def check_new_project(project,sync_params)
# SyncLog.sync_log("***8. begin_to_sync_new_project---------------")
# sync_projects_params = {
# type: "Project",
# ids: sync_params[:id],
# token: get_token,
# sync_params: sync_params,
# new_project_id: project.id
# }
# gitea_main = "https://www.trustie.net/"
# # if request.subdomain === 'testforgeplus'
# # gitea_main = "https://ucloudtest.trustie.net/"
# # end
# SyncProjectsJob.perform_later(sync_projects_params, gitea_main)
# SyncLog.sync_log("***8. end_to_sync_new_project---------------")
# end
# def change_project_praises(project, praises,gitea_main)
# SyncLog.sync_log("***6. begin_to_sync_parises---------------")
# forge_praises_ids = project&.praise_treads&.select(:id)&.pluck(:id)
# diff_target_ids = praises[:ids] - forge_praises_ids
# if diff_target_ids.size > 0
# sync_projects_params = {
# type: "PraiseTread",
# ids: diff_target_ids,
# token: get_token,
# parent_id: project.id
# }
# SyncProjectsJob.perform_later(sync_projects_params,gitea_main)
# SyncLog.sync_log("***6. end_to_sync_parises---------------")
# end
# end
# #检查repository和project_score
# def change_project_score(project, project_scores, repository_params)
# SyncLog.sync_log("***1. begin_to_sync_project_score---------------")
# begin
# pre_project_score = project.project_score
# if pre_project_score.present?
# change_num = 0
# project_scores.each do |k,v|
# unless pre_project_score.send("#{k}") == v
# change_num += 1
# pre_project_score[:"#{k}"] = v
# end
# if k == "changeset_num" && v.to_i > pre_project_score.changeset_num.to_i && repository_params[:url].present?
# SyncRepositoryJob.perform_later(project.owner.try(:login), project.identifier, repository_params, get_sudomain)
# end
# end
# pre_project_score.save! if change_num > 0 #如果 project_score有变化则更新
# else
# ProjectScore.create!(project_scores.merge(project_id: project.id))
# end
# SyncLog.sync_log("***1. end_to_sync_project_score---------------")
# rescue Exception => e
# SyncLog.sync_log("=========change_project_score_errors:#{e}===================")
# end
# end
# def change_project_issues(project, old_issues_params,project_id, gitea_main)
# SyncLog.sync_log("***2. begin_to_syncissues---------------")
# begin
# forge_issue_ids = project&.issues&.select(:id)&.pluck(:id)
# sync_projects_params = {}
# SyncLog.sync_log("***2--01. forge_issue_ids-#{forge_issue_ids.size.to_i}--------------")
# if forge_issue_ids.size.to_i <= old_issues_params[:count].to_i
# diff_issue_ids = old_issues_params[:ids] - forge_issue_ids
# if diff_issue_ids.size == 0 #issue数量一样判断评论是否有增减
# forge_journal_ids = Journal.select([:id, :journalized_id, :journalized_type]).where(journalized_id: forge_issue_ids).pluck(:id)
# diff_journal_ids = old_issues_params[:journals][:ids] - forge_journal_ids
# unless diff_journal_ids.size == 0
# sync_projects_params = {
# type: "Journal",
# ids: diff_journal_ids,
# token: get_token,
# parent_id: project_id
# }
# SyncLog.sync_log("***2--02. sync_projects_params-#{sync_projects_params}--------------")
# SyncProjectsJob.perform_later(sync_projects_params, gitea_main)
# end
# else
# new_diff_ids = diff_issue_ids.in_groups_of(200).map{|k| k.reject(&:blank?)}
# diff_len = new_diff_ids.length
# (1..diff_len).each do |len|
# sync_projects_params = {
# type: "Issue",
# ids: new_diff_ids[len-1],
# token: get_token,
# parent_id: project_id
# }
# SyncLog.sync_log("***2--030#{len}. sync_projects_params_groups-#{sync_projects_params}--------------")
# SyncProjectsJob.perform_later(sync_projects_params, gitea_main)
# end
# # sync_projects_params = {
# # type: "Issue",
# # ids: diff_issue_ids,
# # token: get_token,
# # parent_id: project_id
# # }
# # SyncLog.sync_log("***2--03. sync_projects_params_groups-#{sync_projects_params}--------------")
# # SyncProjectsJob.perform_later(sync_projects_params, gitea_main)
# end
# end
# # SyncProjectsJob.perform_later(sync_projects_params, gitea_main) if sync_projects_params.present?
# SyncLog.sync_log("***2. end_to_syncissues---------------")
# rescue Exception => e
# SyncLog.sync_log("=========change_project_issues_errors:#{e}===================")
# end
# end
# def change_project_watchers(project, watchers,gitea_main)
# SyncLog.sync_log("***5. begin_to_sync_watchers---------------")
# forge_watchers_ids = project&.watchers&.select(:id)&.pluck(:id)
# if forge_watchers_ids.size.to_i <= watchers[:count].to_i
# diff_target_ids = watchers[:ids] - forge_watchers_ids
# if diff_target_ids.size > 0
# sync_projects_params = {
# type: "Watcher",
# ids: diff_target_ids,
# token: get_token,
# parent_id: project.id
# }
# SyncProjectsJob.perform_later(sync_projects_params,gitea_main)
# end
# end
# SyncLog.sync_log("***5. begin_to_sync_watchers---------------")
# end
# def change_project_versions(project, versions,gitea_main)
# SyncLog.sync_log("***4. begin_to_sync_versions---------------")
# forge_version_ids = project&.versions&.select(:id)&.pluck(:id)
# if forge_version_ids.size <= versions[:count].to_i
# diff_version_ids = versions[:ids] - forge_version_ids
# if diff_version_ids.size > 0
# sync_projects_params = {
# type: "Version",
# ids: diff_version_ids,
# token: get_token,
# parent_id: project.id
# }
# SyncProjectsJob.perform_later(sync_projects_params,gitea_main)
# end
# SyncLog.sync_log("***4. end_to_sync_versions---------------")
# end
# end
# def change_project_members(project, members,gitea_main)
# SyncLog.sync_log("***3. begin_to_sync_members---------------")
# forge_member_ids = project&.members&.select(:id)&.pluck(:id)
# if forge_member_ids.size <= members[:count]
# diff_member_ids = members[:ids] - forge_member_ids
# if diff_member_ids.size > 0
# sync_projects_params = {
# type: "Member",
# ids: diff_member_ids,
# token: get_token,
# parent_id: project.id
# }
# SyncProjectsJob.perform_later(sync_projects_params,gitea_main)
# end
# SyncLog.sync_log("***3. end_to_sync_members---------------")
# end
# end
# def check_token
# sync_params = params[:sync_params]
# unless sync_params[:token] && sync_params[:token] == get_token
# render json: {message: "token_errors"}
# end
# end
# def get_token
# "34c82f51e0b699d9d16d70fd6497c9b1e4821d6ea3e872558a6537a091076b8e"
# end
# def get_sudomain
# SyncLog.sync_log("=================request.subdomain:#{request.subdomain}========")
# gitea_main = "gitea.trustie.net"
# if request.subdomain === 'testforgeplus'
# gitea_main = "testgitea2.trustie.net"
# # elsif request.subdomain === 'forgeplus'
# # gitea_main = "gitea.trustie.net"
# end
# return gitea_main
# end
end

View File

@ -1,11 +0,0 @@
class TagDisciplinesController < ApplicationController
before_action :require_login
def create
sub_discipline = SubDiscipline.find_by!(id: params[:sub_discipline_id])
tip_exception("重复的知识点") if sub_discipline.tag_disciplines.exists?(name: params[:name].to_s.strip)
tag_discipline = TagDiscipline.create!(name: params[:name].to_s.strip, sub_discipline: sub_discipline, user_id: current_user.id,
position: sub_discipline.tag_disciplines.pluck(:position).max + 1)
render_ok({tag_discipline_id: tag_discipline.id})
end
end

View File

@ -1,74 +0,0 @@
class TemTestsController < ApplicationController
before_action :set_tem_test, only: [:show, :edit, :update, :destroy]
# GET /tem_tests
# GET /tem_tests.json
def index
@tem_tests = TemTest.all
end
# GET /tem_tests/1
# GET /tem_tests/1.json
def show
end
# GET /tem_tests/new
def new
@tem_test = TemTest.new
end
# GET /tem_tests/1/edit
def edit
end
# POST /tem_tests
# POST /tem_tests.json
def create
@tem_test = TemTest.new(tem_test_params)
respond_to do |format|
if @tem_test.save
format.html { redirect_to @tem_test, notice: 'Tem test was successfully created.' }
format.json { render :show, status: :created, location: @tem_test }
else
format.html { render :new }
format.json { render json: @tem_test.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tem_tests/1
# PATCH/PUT /tem_tests/1.json
def update
respond_to do |format|
if @tem_test.update(tem_test_params)
format.html { redirect_to @tem_test, notice: 'Tem test was successfully updated.' }
format.json { render :show, status: :ok, location: @tem_test }
else
format.html { render :edit }
format.json { render json: @tem_test.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tem_tests/1
# DELETE /tem_tests/1.json
def destroy
@tem_test.destroy
respond_to do |format|
format.html { redirect_to tem_tests_url, notice: 'Tem test was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tem_test
@tem_test = TemTest.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def tem_test_params
params.require(:tem_test).permit(:name, :email)
end
end

View File

@ -1,5 +0,0 @@
class TemplatesController < ApplicationController
def show
@template = EcTemplate.find_by_name!(params[:name])
end
end

View File

@ -1,37 +0,0 @@
class TidingsController < ApplicationController
include PaginateHelper
before_action :require_login
after_action :update_onclick_time!, only: [:index]
def index
tidings = current_user.tidings.visible
@onclick_time = current_user.click_time
tiding_types =
case params[:type]
when 'notice' then 'System'
when 'apply' then 'Apply'
when 'course' then %w(HomeworkCommon Exercise Poll GraduationTask GraduationTopic)
when 'project' then 'Project'
when 'interaction' then %w(Comment Mentioned Praise Fan)
when 'project_package' then %w(Created Destroyed Bidding BiddingEnd BiddingWon BiddingLost)
end
tidings = tidings.where(tiding_type: tiding_types) if tiding_types.present?
tidings = tidings.where(container_type: 'JoinCourse', status: 0) if params[:type] == 'course_apply'
# @course_apply_count = tidings.where("created_at > '#{@onclick_time}'").where(container_type: 'JoinCourse', status: 0).count
@course_apply_count = tidings.where(container_type: 'JoinCourse', status: 0).count
tidings = tidings.where(container_type: 'ProjectPackage') if params[:type] == 'project_package'
@count = tidings.count
@tidings = paginate(tidings.order(created_at: :desc), per_page: 10)
end
private
def update_onclick_time!
current_user.onclick_time.touch(:onclick_time)
end
end

View File

@ -1,22 +0,0 @@
class TrialAppliesController < ApplicationController
before_action :require_user_login
def create
Users::ApplyTrailService.call(current_user, create_params)
render_ok
rescue Users::ApplyTrailService::Error => ex
render_error(ex.message)
end
private
def create_params
params.permit(:phone, :code, :reason).merge(remote_ip: request.remote_ip)
end
def require_user_login
return if User.current.logged?
render_unauthorized
end
end

View File

@ -1,72 +0,0 @@
class TrustieHacksController < ApplicationController
before_action :require_admin, :except => [:index, :entry]
before_action :require_login, :except => [:index]
before_action :find_hackathon
before_action :find_hack, :except => [:create, :index, :edit_hackathon, :update_hackathon]
def index
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 16
search = params[:search]
hacks = @hackathon.trustie_hacks
if search
hacks = hacks.where("name like ?", "%#{search}%")
end
@hackathon_users_count = hacks.blank? ? 0 : hacks.sum(:hack_users_count)
@hacks_count = hacks.count
@hacks = hacks.page(page).per(limit)
end
def edit;end
def create
@hackathon.trustie_hacks.create!(name: params[:name], description: params[:description])
render_ok
end
def update
@hack.update_attributes(name: params[:name], description: params[:description])
render_ok
end
def destroy
@hack.destroy
render_ok
end
def edit_hackathon
end
def update_hackathon
@hackathon.update_attributes(name: params[:name], description: params[:description])
render_ok
end
# 报名入口
def entry
if @hack.hack_users.exists?(user_id: current_user.id)
render_error('已经报名,请勿重复操作')
else
@hack.hack_users.create(user_id: current_user.id)
render_ok
end
end
private
def find_hackathon
@hackathon = TrustieHackathon.first ||
TrustieHackathon.create!(name: params[:name], description: params[:description])
end
def find_hack
@hack = TrustieHack.find params[:id]
end
end

View File

@ -1,8 +1,11 @@
class UsersController < ApplicationController
include Ci::DbConnectable
before_action :load_user, only: [:show, :homepage_info]
before_action :check_user_exist, only: [:show, :homepage_info]
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users]
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users]
before_action :require_login, only: %i[me list]
before_action :connect_to_ci_database, only: :get_user_info, if: -> { current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification? }
skip_before_action :check_sign, only: [:attachment_show]
def list
@ -11,7 +14,35 @@ class UsersController < ApplicationController
@users = paginate(scope)
end
def show;end
def show
#待办事项,现在未做
@undo_events = 0
#用户的组织数量
# @user_composes_count = @user.composes.size
@user_composes_count = 0
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.projects.visible
@projects_common_count = user_projects.common.size
@projects_mirrior_count = user_projects.mirror.size
@projects_sync_mirrior_count = user_projects.sync_mirror.size
end
def watch_users
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
if params[:search].present?
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
watchers = watchers.where(watchable_id: search_user_ids)
end
@watchers_count = watchers.size
@watchers = paginate(watchers)
end
def fan_users
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
watchers = watchers.joins(:user).where("LOWER(concat(users.lastname, users.firstname, users.login)) LIKE ?", "%#{params[:search].split(" ").join('|')}%") if params[:search].present?
@watchers_count = watchers.size
@watchers = paginate(watchers)
end
def update
@user = User.find params[:id]
@ -29,25 +60,6 @@ class UsersController < ApplicationController
@user = current_user
# TODO 等消息上线再打开注释
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
@course =
if params[:course_id]
Course.find params[:course_id]
elsif params[:board_id]
Board.find(params[:board_id]).course
elsif params[:graduation_topic_id]
GraduationTopic.find(params[:graduation_topic_id]).course
elsif params[:graduation_group_id]
GraduationGroup.find(params[:graduation_group_id]).course
elsif params[:graduation_work_id]
GraduationWork.find(params[:graduation_work_id]).course
elsif params[:graduation_task_id]
GraduationTask.find(params[:graduation_task_id]).course
elsif params[:poll_id]
Poll.find(params[:poll_id]).course
elsif params[:attachment_id]
Attachment.find(params[:attachment_id]).course
end
@course_identity = current_user.course_identity(@course) if @course
rescue Exception => e
uid_logger_error(e.message)
missing_template
@ -72,14 +84,14 @@ class UsersController < ApplicationController
# Redo: 消息总数缓存
def get_navigation_info
@old_domain = edu_setting('old_edu_host')
@user = current_user
# 新消息数
@new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
@user_url = "/users/#{@user.login}"
@career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
@auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
# @old_domain = edu_setting('old_edu_host')
# @user = current_user
# # 新消息数
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
#
# @user_url = "/users/#{@user.login}"
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
end
# 用户回复功能
@ -104,8 +116,14 @@ class UsersController < ApplicationController
@projects = projects.select(:id, :name)
end
# 个人主页信息
def homepage_info;end
#TODO 个人主页信息forge上弃用-hs, 0602
def homepage_info
#待办事项,现在未做
@undo_events = 10
#用户的组织数量
# @user_composes_count = @user.composes.size
@user_composes_count = 10
end
def brief_introduction
content = params[:content].to_s.strip
@ -122,17 +140,98 @@ class UsersController < ApplicationController
render_error(ex.message)
end
# 其他平台登录后必须将token同步到forge平台实现sso登录功能
def sync_token
return render_error('未找相关用户!') unless @user
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
token.update_column(:value, params[:token])
render_ok
end
def trustie_related_projects
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
projects_json = []
domain_url = EduSetting.get('host_name') + '/projects'
if projects.present?
projects.each do |p|
project_url = "/#{p.owner.login}/#{p.identifier}"
pj = {
id: p.id,
name: p.name,
is_public: p.is_public,
updated_on: p.updated_on.strftime("%Y-%m-%d"),
status: p.status,
is_member: p.member?(current_user.try(:id)),
owner: {
name: p.owner.try(:show_real_name),
login: p.owner.login
},
members_count: p&.members.size,
issues_count: p.issues_count - p.pull_requests_count,
commits_count: p&.project_score&.changeset_num.to_i,
http_url: domain_url + project_url,
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
http_issues_url: domain_url + project_url + "/issues",
http_commits_url: domain_url + project_url + "/commits",
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
}
projects_json.push(pj)
end
end
Rails.logger.info("==========projects_json========+########{projects_json}")
render json: { projects: projects_json.present? ? projects_json : {} }
end
def trustie_projects
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
projects = Project.visible
projects = projects.joins(:members).where(members: { user_id: user_id })
search = params[:search].to_s.strip
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
projects = projects.select(:id, :name).limit(10).as_json
render json: { projects: projects }
end
def projects
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
@total_count = scope.size
@projects = paginate(scope)
end
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
# 该方法主要用于别的平台初次部署对接forge平台同步用户后gitea平台对应的用户密码与forge平台用户密码不一致是问题
def sync_gitea_pwd
return render_error("未找到相关的用户") if @user.blank?
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
flag ? render_ok : render_error('同步失败!')
end
# TODO
# 同步trusite平台用户的salt信息只需同步一次同步完成后该方法可以删除
def sync_salt
user = User.find_by_login params[:login]
return if user.blank?
user.update_column(:salt, params[:salt])
render_ok
end
private
def load_user
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
end
def user_params
params.require(:user).permit(:nickname, :lastname, :show_realname,
params.require(:user).permit(:nickname, :lastname, :show_realname,:login,:mail,
user_extension_attributes: [
:gender, :location, :location_city,
:occupation, :technical_title,
:school_id, :department_id]
:school_id, :department_id,:identity, :student_id, :description]
)
end

View File

@ -1,27 +0,0 @@
class UsersForPartnersController < ApplicationController
include Base::PaginateHelper
before_action :check_partner_manager_permission!
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
users = Admins::UserQuery.call(search_params)
@users = paginate users.includes(user_extension: :school)
end
private
def search_params
params.permit(:name, :sort_by, :sort_direction)
end
def check_partner_manager_permission!
partner = Partner.find(params[:partner_id])
return if admin_or_business?
return if partner.admin_partner_manager_group.partner_managers.exists?(user: current_user)
render_forbidden
end
end

View File

@ -1,6 +1,6 @@
class VersionReleasesController < ApplicationController
before_action :find_project
before_action :set_user_and_project
before_action :load_repository
before_action :set_user
before_action :require_login, except: [:index]
before_action :find_version , only: [:edit, :update, :destroy]
@ -8,13 +8,13 @@ class VersionReleasesController < ApplicationController
version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call
@version_releases = version_releases
@user_permission = current_user.present? && (current_user == @user || current_user.admin?)
@forge_releases = @repository.version_releases.select(:id,:version_gid).includes(:attachments)
end
def new
#获取所有的分支
@all_branches = []
get_all_branches = Gitea::Repository::BranchesService.new(@user, @repository.try(:identifier)).call
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call
if get_all_branches && get_all_branches.size > 0
get_all_branches.each do |b|
@all_branches.push(b["name"])
@ -34,14 +34,7 @@ class VersionReleasesController < ApplicationController
else
ActiveRecord::Base.transaction do
begin
version_params = {
body: params[:body],
draft: params[:draft] || false,
name: params[:name],
prerelease: params[:prerelease] || false,
tag_name: params[:tag_name],
target_commitish: params[:target_commitish] || "master" #分支
}
version_params = releases_params
version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id))
if version_release.save!
git_version_release = Gitea::Versions::CreateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params).call
@ -54,6 +47,9 @@ class VersionReleasesController < ApplicationController
}
version_release.update_attributes!(update_params)
version_release.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
if params[:attachment_ids].present?
create_attachments(params[:attachment_ids], version_release)
end
normal_status(0, "发布成功")
else
normal_status(-1, "发布失败")
@ -70,7 +66,7 @@ class VersionReleasesController < ApplicationController
end
def edit
@version_attachments = @version.attachments
end
def update
@ -81,19 +77,15 @@ class VersionReleasesController < ApplicationController
else
ActiveRecord::Base.transaction do
begin
version_params = {
body: params[:body],
draft: params[:draft] || false,
name: params[:name],
prerelease: params[:prerelease],
tag_name: params[:tag_name],
target_commitish: params[:target_commitish] || "master" #分支
}
version_params = releases_params
if @version.update_attributes!(version_params)
create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present?
git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call
unless git_version_release
raise Error, "更新失败"
end
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")
@ -131,14 +123,8 @@ class VersionReleasesController < ApplicationController
private
def set_user_and_project
# @project = Project.find_by_id(params[:project_id])
@repository = @project.repository #项目的仓库
@user = @project.owner
unless @user.present? && @project.present? && @repository.present?
normal_status(-1, "仓库不存在")
end
def set_user
@user = @repository.user
end
def find_version
@ -148,4 +134,27 @@ class VersionReleasesController < ApplicationController
end
end
def releases_params
{
body: params[:body],
draft: params[:draft] || false,
name: params[:name],
prerelease: params[:prerelease] || false,
tag_name: params[:tag_name],
target_commitish: params[:target_commitish] || "master" #分支
}
end
def create_attachments(attachment_ids, target)
attachment_ids.each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
unless attachment.blank?
attachment.container = target
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
end
end

View File

@ -1,6 +1,6 @@
class VersionsController < ApplicationController
before_action :require_login
before_action :find_project
before_action :require_login, except: [:index, :show]
before_action :load_repository
before_action :check_issue_permission, except: [:show, :index]
before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status]
@ -166,4 +166,4 @@ class VersionsController < ApplicationController
end
end
end
end

View File

@ -1,17 +1,18 @@
class WatchersController < ApplicationController
before_action :require_login, except: %i[index]
before_action :find_project_with_id
# before_action :find_project_with_id
before_action :get_target
def index
scope = @project.watchers.includes(:user)
scope = @target.watchers.includes(:user)
@watchers = paginate(scope)
end
def unfollow
begin
return normal_status(2, "你还没有关注哦") unless current_user.watched?(@project)
current_user.unwatch!(@project)
render_ok
return normal_status(2, "你还没有关注哦") unless current_user.watched?(@target)
current_user.unwatch!(@target)
render_ok({watchers_count: @target.watchers_count, watched: false})
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -21,9 +22,9 @@ class WatchersController < ApplicationController
def follow
begin
return normal_status(2, "你已关注了") if current_user.watched?(@project)
current_user.watch!(@project)
render_ok
return normal_status(2, "你已关注了") if current_user.watched?(@target)
current_user.watch!(@target)
render_ok({watchers_count: @target.watchers_count, watched: true})
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -32,11 +33,28 @@ class WatchersController < ApplicationController
end
def check_watch
is_watch = current_user.watched?(@project)
is_watch = current_user.watched?(@target)
render_result(is_watch ? 1 : 0)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
private
def get_target
target_type = params[:target_type].to_s
case target_type
when "project"
@target = target_type.capitalize.constantize.find_by(id: params[:id])
else
@target = target_type.capitalize.constantize.find_by(login: params[:id]) #用户
end
unless @target.present?
normal_status(-1, "目标不存在")
end
end
end

Some files were not shown because too many files have changed in this diff Show More