@ -18,16 +18,18 @@ class ShixunsController < ApplicationController
before_action :find_repo_name , only : [ :repository , :commits , :file_content , :update_file , :shixun_exec , :copy ,
:add_file , :jupyter_exec ]
before_action :allowed , only : [ :update , :close , :update_propaedeutics , :settings , :publish ,
:shixun_members_added , :change_manager , :collaborators_delete ,
:cancel_ publish, :add_collaborators , :add _file]
before_action :allowed , only : [ :update , :close , :update_propaedeutics , :settings , :publish , :apply_public , :upload_git_folder ,
:shixun_members_added , :change_manager , :collaborators_delete , :upload_git_file ,
:cancel_ apply_public, :cancel_ publish, :add_collaborators , :add _file, :delete_git _file]
before_action :portion_allowed , only : [ :copy ]
before_action :special_allowed , only : [ :send_to_course , :search_user_courses ]
before_action :shixun_marker , only : [ :new , :create ]
skip_before_action :check_sign , only : [ :download_file ]
## 获取课程列表
def index
@shixuns = current_laboratory . shixuns . unhidden
@shixuns = current_laboratory . shixuns . unhidden . publiced
## 方向
if params [ :tag_level ] . present? && params [ :tag_id ] . present?
@ -67,15 +69,11 @@ class ShixunsController < ApplicationController
## 排序参数
bsort = params [ :sort ] || 'desc'
case params [ :order_by ] || 'publish_time'
when 'new'
@shixuns = @shixuns . order ( " shixuns.status = 2 desc, shixuns.created_at #{ bsort } " )
case params [ :order_by ] || 'new'
when 'hot'
@shixuns = @shixuns . order ( " shixuns.status = 2 desc, shixuns.myshixuns_count #{ bsort } " )
when 'mine'
@shixuns = @shixuns . order ( " shixuns.created_at #{ bsort } " )
@shixuns = @shixuns . order ( " shixuns.public = 2 desc, shixuns.myshixuns_count #{ bsort } " )
else
@shixuns = @shixuns . order ( " shixuns. status = 2 desc, shixuns.publish_time #{ bsort } " )
@shixuns = @shixuns . order ( " shixuns.public = 2 desc, shixuns.publish_time #{ bsort } " )
end
# 用id计数会快10+MS左右,对于搜索的内容随着数据的增加,性能会提升一些。
@ -169,9 +167,10 @@ class ShixunsController < ApplicationController
def show_right
owner = @shixun . owner
#@fans_count = owner.fan_count
#@followed_count = owner.follow_count
@user_own_shixuns = owner . shixuns . published . count
@user_tags = @shixun . user_tags_name ( current_user )
@shixun_tags = @shixun . challenge_tags_name
@myshixun = @shixun . myshixuns . find_by ( user_id : current_user . id )
end
# 排行榜
@ -207,7 +206,7 @@ class ShixunsController < ApplicationController
@new_shixun = Shixun . new
@new_shixun . attributes = @shixun . attributes . dup . except ( " id " , " user_id " , " visits " , " gpid " , " status " , " identifier " , " averge_star " ,
" homepage_show " , " repo_name " , " myshixuns_count " , " challenges_count " ,
" can_copy " , " created_at " , " updated_at " )
" can_copy " , " created_at " , " updated_at " , " public " )
@new_shixun . user_id = User . current . id
@new_shixun . averge_star = 5
@new_shixun . identifier = generate_identifier Shixun , 8
@ -218,7 +217,8 @@ class ShixunsController < ApplicationController
if @shixun . shixun_info . present?
ShixunInfo . create! ( shixun_id : @new_shixun . id ,
description : @shixun . description ,
evaluate_script : @shixun . evaluate_script )
evaluate_script : @shixun . evaluate_script ,
fork_reason : params [ :reason ] . to_s . strip )
end
# 同步私密版本库
@ -265,7 +265,24 @@ class ShixunsController < ApplicationController
project_fork ( @new_shixun , @repo_path , current_user . login )
ShixunMember . create! ( :user_id = > User . current . id , :shixun_id = > @new_shixun . try ( :id ) , :role = > 1 )
# 如果是jupyter, 先创建一个目录,为了挂载(因为后续数据集, 开启Pod后环境在没销毁前, 你上传数据集是挂载不上目录的, 因此要先创建目录, 方便中间层挂载)
if @new_shixun . is_jupyter?
folder = EduSetting . get ( 'shixun_folder' )
raise " 存储目录未定义 " unless folder . present?
path = " #{ folder } / #{ @new_shixun . identifier } "
FileUtils . mkdir_p ( path , :mode = > 0777 ) unless File . directory? ( path )
# 复制数据集
save_path = File . join ( folder , @shixun . identifier )
@shixun . data_sets . each do | set |
new_date_set = Attachment . new
new_date_set . attributes = set . attributes . dup . except ( " id " , " container_id " , " disk_directory " )
new_date_set . container_id = @new_shixun . id
new_date_set . disk_directory = @new_shixun . identifier
new_date_set . save!
FileUtils . cp ( " #{ save_path } / #{ set . relative_path_filename } " , path )
end
end
# 同步复制关卡
if @shixun . challenges . present?
@shixun . challenges . each do | challenge |
@ -344,7 +361,11 @@ class ShixunsController < ApplicationController
#合作者
def collaborators
@user = current_user
@members = @shixun . shixun_members . includes ( :user )
## 分页参数
page = params [ :page ] || 1
limit = params [ :limit ] || 10
@member_count = @shixun . shixun_members . count
@members = @shixun . shixun_members . order ( " role = 1 desc, created_at asc " ) . includes ( :user ) . page ( page ) . per ( limit )
end
def fork_list
@ -365,12 +386,12 @@ class ShixunsController < ApplicationController
end
def create
begin
@shixun = CreateShixunService . call ( current_user , shixun_params , params )
rescue = > e
logger_error ( " shixun_create_error: #{ e . message } " )
tip_exception ( " 创建实训失败! " )
end
@shixun = CreateShixunService . call ( current_user , shixun_params , params )
end
# 保存jupyter到版本库
def update_jupyter
jupyter_save_with_shixun ( @shixun , params [ :jupyter_port ] )
end
def update
@ -399,25 +420,24 @@ class ShixunsController < ApplicationController
@shixun . shixun_info . update_attributes ( shixun_info_params )
# 镜像变动
@shixun . shixun_mirror_repositories . where . not ( mirror_repository_id : old_mirror_ids ) . destroy_all
@shixun . shixun_mirror_repositories . create! ( new_mirror_id )
@shixun . shixun_mirror_repositories . create! ( new_mirror_id ) if new_mirror_id . present?
# 镜像变动要更换服务配置
@shixun . shixun_service_configs . where . not ( mirror_repository_id : old_mirror_ids ) . destroy_all
@shixun . shixun_service_configs . create! ( service_create_params )
@shixun . shixun_service_configs . create! ( service_create_params ) if service_create_params . present?
service_update_params & . map do | service |
smr = @shixun . shixun_service_configs . find_by ( mirror_repository_id : service [ :mirror_repository_id ] )
smr . update_attributes ( service )
logger . info ( " # # # # # # # # smr: #{ smr } " )
smr . update_attributes ( service ) if smr . present?
end
# 添加第二仓库(管理员权限)
if current_user . admin_or_business?
if params [ :is_secret_repository ]
add_secret_repository if @shixun . shixun_secret_repository . blank?
else
# 如果有仓库,就要删
if @shixun . shixun_secret_repository & . repo_name
@shixun . shixun_secret_repository . lock!
GitService . delete_repository ( repo_path : @shixun . shixun_secret_repository . repo_path )
@shixun . shixun_secret_repository . destroy
end
if params [ :is_secret_repository ]
add_secret_repository if @shixun . shixun_secret_repository . blank?
else
# 如果有仓库,就要删
if @shixun . shixun_secret_repository & . repo_name
@shixun . shixun_secret_repository . lock!
GitService . delete_repository ( repo_path : @shixun . shixun_secret_repository . repo_path )
@shixun . shixun_secret_repository . destroy
end
end
end
@ -449,7 +469,13 @@ class ShixunsController < ApplicationController
def update_learn_setting
begin
ActiveRecord :: Base . transaction do
@shixun . update_attributes! ( shixun_params )
update_params =
if params [ :shixun ] [ :vnc ]
shixun_params . merge ( vnc_evaluate : 1 )
else
shixun_params
end
@shixun . update_attributes! ( update_params )
end
rescue = > e
uid_logger_error ( " 实训学习页面设置失败-------- #{ e . message } " )
@ -458,12 +484,71 @@ class ShixunsController < ApplicationController
end
# Jupyter数据集
def jupyter _data_sets
def get _data_sets
page = params [ :page ] || 1
limit = params [ :limit ] || 10
data_sets = @shixun . jupyter_ data_sets
data_sets = @shixun . data_sets
@data_count = data_sets . count
@data_sets = data_sets . page ( page ) . per ( limit )
@data_sets = data_sets . order ( " created_on desc " ) . page ( page ) . per ( limit )
@absolute_folder = edu_setting ( 'shixun_folder' )
end
# 实训测试集附件
def upload_data_sets
begin
upload_file = params [ " file " ]
raise " 未上传文件 " unless upload_file
folder = edu_setting ( 'shixun_folder' )
raise " 存储目录未定义 " unless folder . present?
rep_name = @shixun . data_sets . pluck ( :filename ) . include? ( upload_file . original_filename )
raise " 文件名已经存在 \" #{ upload_file . original_filename } \" , 请删除后再上传 " if rep_name
tpm_folder = params [ :identifier ] # 这个是实训的identifier
save_path = File . join ( folder , tpm_folder )
ext = file_ext ( upload_file . original_filename )
local_path , digest = file_save_to_local ( save_path , upload_file . tempfile , ext )
content_type = upload_file . content_type . presence || 'application/octet-stream'
disk_filename = local_path [ save_path . size + 1 , local_path . size ]
@attachment = Attachment . where ( disk_filename : disk_filename ,
author_id : current_user . id ) . first
if @attachment . blank?
@attachment = Attachment . new
@attachment . filename = upload_file . original_filename
@attachment . disk_filename = local_path [ save_path . size + 1 , local_path . size ]
@attachment . filesize = upload_file . tempfile . size
@attachment . content_type = content_type
@attachment . digest = digest
@attachment . author_id = current_user . id
@attachment . disk_directory = tpm_folder
@attachment . container_id = @shixun . id
@attachment . container_type = @shixun . class . name
@attachment . attachtype = 2
@attachment . save!
else
logger . info " 文件已存在, id = #{ @attachment . id } , filename = #{ @attachment . filename } "
end
render_ok
rescue = > e
uid_logger_error ( e . message )
tip_exception ( e . message )
end
end
# 多文件删除
def destroy_data_sets
files = Attachment . where ( id : params [ :id ] )
shixun_folder = edu_setting ( " shixun_folder " )
begin
files . each do | file |
file_path = " #{ shixun_folder } / #{ file . relative_path_filename } "
delete_file ( file_path )
end
files . destroy_all
render_ok
rescue = > e
uid_logger_error ( e . message )
tip_exception ( e . message )
end
end
def apply_shixun_mirror
@ -529,6 +614,8 @@ class ShixunsController < ApplicationController
# @evaluate_scirpt = @shixun.evaluate_script || "无"
end
# 获取脚本内容
def get_script_contents
mirrir_script = MirrorScript . find ( params [ :script_id ] )
@ -687,7 +774,7 @@ class ShixunsController < ApplicationController
# jupyter开启挑战
def jupyter_exec
begin
if is_shixun_opening?
tip_show_exception ( - 3 , " #{ @shixun . opening_time . strftime ( '%Y-%m-%d %H:%M:%S' ) } " )
end
@ -697,70 +784,75 @@ class ShixunsController < ApplicationController
else
commit = GitService . commits ( repo_path : @repo_path ) . try ( :first )
uid_logger ( " First comit # # # # # # # #{ commit } " )
tip_exception ( " 开启 实战前请先在版本库中提交代码 " ) if commit . blank?
tip_exception ( " 开启 挑战前, 请先在Jupyter中填写内容并保存 " ) if commit . blank?
commit_id = commit [ " id " ]
cloud_bridge = edu_setting ( 'cloud_bridge' )
myshixun_identifier = generate_identifier Myshixun , 10
ActiveRecord :: Base . transaction do
@myshixun = @shixun . myshixuns . create! ( user_id : current_user . id , identifier : myshixun_identifier ,
modify_time : @shixun . modify_time , reset_time : @shixun . reset_time ,
onclick_time : Time . now , commit_id : commit_id )
# fork仓库
project_fork ( @myshixun , @repo_path , current_user . login )
rep_url = Base64 . urlsafe_encode64 ( repo_ip_url @repo_path )
uri = " #{ cloud_bridge } /bridge/game/openGameInstance "
params = { tpiID : " #{ myshixun . id } " , tpmGitURL : rep_url , tpiRepoName : myshixun . repo_name . split ( " / " ) . last }
interface_post uri , params , 83 , " 实训云平台繁忙( 繁忙等级: 83) "
begin
ActiveRecord :: Base . transaction do
@myshixun = @shixun . myshixuns . create! ( user_id : current_user . id , identifier : myshixun_identifier ,
modify_time : @shixun . modify_time , reset_time : @shixun . reset_time ,
onclick_time : Time . now , commit_id : commit_id )
# fork仓库
project_fork ( @myshixun , @repo_path , current_user . login )
rep_url = Base64 . urlsafe_encode64 ( repo_ip_url @repo_path )
uri = " #{ cloud_bridge } /bridge/game/openGameInstance "
params = { tpiID : " #{ @myshixun . id } " , tpmGitURL : rep_url , tpiRepoName : @myshixun . repo_name . split ( " / " ) . last }
interface_post uri , params , 83 , " 服务器出现问题,请重置环境 "
end
rescue = > e
uid_logger_error ( e . message )
tip_exception ( " 服务器出现问题,请重置环境 " )
end
end
rescue = > e
uid_logger_error ( e . message )
tip_exception ( " 实训云平台繁忙( 繁忙等级: 81) " )
end
end
def publish
@status = 0
@position = [ ]
begin
if @shixun . challenges . count == 0
@status = 4
else
@shixun . challenges . each do | challenge |
if challenge . challenge_tags . count == 0
@status = 3
@position << challenge . position
unless @shixun . is_jupyter?
if @shixun . challenges . count == 0
@status = 4
else
@shixun . challenges . each do | challenge |
if challenge . challenge_tags . count == 0
@status = 3
@position << challenge . position
end
end
end
unfinish_challenge = @shixun . challenges . where ( :st = > 0 , :path = > nil )
if unfinish_challenge . count > 0 && ! @shixun . is_choice_type?
@status = 2
@pos = [ ]
unfinish_challenge . each do | challenge |
@pos << challenge . position
unfinish_challenge = @shixun . challenges . where ( :st = > 0 , :path = > nil )
if unfinish_challenge . count > 0 && ! @shixun . is_choice_type?
@status = 2
@pos = [ ]
unfinish_challenge . each do | challenge |
@pos << challenge . position
end
end
end
end
if @status == 0
@shixun . update_attributes! ( :status = > 1 )
apply = ApplyAction . where ( :container_type = > " ApplyShixun " , :container_id = > @shixun . id ) . order ( " created_at desc " ) . first
if apply && apply . status == 0
@status = 0
else
ApplyAction . create ( :container_type = > " ApplyShixun " , :container_id = > @shixun . id , :user_id = > current_user . id , :status = > 0 )
#begin
# status = Trustie::Sms.send(mobile: '18711011226', send_type:'publish_shixun' , name: '管理员')
#rescue => e
# Rails.logger.error "发送验证码出错: #{e}"
#end
@status = 1
end
@shixun . update_attributes! ( :status = > 2 )
end
rescue Exception = > e
logger . error ( " pushlish game #{ e } " )
end
end
def apply_public
tip_exception ( - 1 , " 请先发布实训再申请公开 " ) if @shixun . status != 2
ActiveRecord :: Base . transaction do
@shixun . update_attributes! ( public : 1 )
apply = ApplyAction . where ( :container_type = > " ApplyShixun " , :container_id = > @shixun . id ) . order ( " created_at desc " ) . first
if apply && apply . status == 0
@status = 0
else
ApplyAction . create ( :container_type = > " ApplyShixun " , :container_id = > @shixun . id , :user_id = > current_user . id , :status = > 0 )
end
end
normal_status ( 0 , " 申请成功 " )
end
# 设置私密版本库的在tpm中的目录
def set_secret_dir
raise ( " 设置路径不能为空 " ) if params [ :secret_dir_path ] . blank?
@ -792,7 +884,36 @@ class ShixunsController < ApplicationController
author_name = current_user . real_name
author_email = current_user . git_mail
@content = update_file_content content , @repo_path , @path , author_email , author_name , " Edit by browser "
end
end
def upload_git_file
upload_file = params [ " file " ]
uid_logger ( " # # # # # # # # # # # # # # # # # # # # # # # # # file_params # # # #{ params [ " #{ params [ :file ] } " ] } " )
raise " 未上传文件 " unless upload_file
content = upload_file . tempfile . read
author_name = current_user . real_name
author_email = current_user . git_mail
message = params [ :message ] || " upload file by browser "
update_file_content ( content , @repo_path , @path , author_email , author_name , message )
render_ok
end
# 上传目录
def upload_git_folder
author_name = current_user . real_name
author_email = current_user . git_mail
message = params [ :message ] || " upload folder by browser "
git_add_folder ( @path , author_name , author_email , message )
render_ok
end
def delete_git_file
author_name = current_user . real_name
author_email = current_user . git_mail
message = params [ :message ] || " delete file by browser "
git_delete_file ( @path , author_name , author_email , message )
render_ok
end
def add_collaborators
member_ids = " ( " + @shixun . shixun_members . map ( & :user_id ) . join ( ',' ) + " ) "
@ -826,16 +947,20 @@ class ShixunsController < ApplicationController
# 搜索成员
if request . get?
@collaborators = @shixun . shixun_members . where ( " user_id != #{ @shixun . user_id } " )
else
if params [ :user_id ]
man_member = ShixunMember . where ( :shixun_id = > @shixun . id , :user_id = > @shixun . user_id ) . first
cha_member = ShixunMember . where ( :user_id = > params [ :user_id ] , :shixun_id = > @shixun . id ) . first
if man_member && cha_member
man_member . update_attribute ( :role , 2 )
cha_member . update_attribute ( :role , 1 )
@shixun . update_attribute ( :user_id , cha_member . user_id )
end
end
else
begin
raise ( " 请先选择成员 " ) if params [ :user_id ] . blank?
man_member = ShixunMember . where ( :shixun_id = > @shixun . id , :user_id = > @shixun . user_id ) . first
cha_member = ShixunMember . where ( :user_id = > params [ :user_id ] , :shixun_id = > @shixun . id ) . first
if man_member && cha_member
man_member . update_attribute ( :role , 2 )
cha_member . update_attribute ( :role , 1 )
@shixun . update_attribute ( :user_id , cha_member . user_id )
end
rescue = > e
logger . error ( " # # # # # # change_manager_error: #{ e . message } " )
render_error ( e . message )
end
end
end
@ -898,14 +1023,24 @@ class ShixunsController < ApplicationController
:disposition = > 'attachment' #inline can open in browser
end
# 撤销申请公开
def cancel_apply_public
tip_exception ( " 实训已经公开,无法撤销 " ) if @shixun . public == 2
ActiveRecord :: Base . transaction do
apply = ApplyAction . where ( :container_type = > " ApplyShixun " , :container_id = > @shixun . id ) . order ( " created_at desc " ) . first
if apply && apply . status == 0
apply . update_attributes! ( status : 3 )
apply . tidings & . destroy_all
end
@shixun . update_column ( :public , 0 )
end
normal_status ( 0 , " 成功撤销申请 " )
end
# 撤销发布
def cancel_publish
tip_exception ( " 实训已经发布,无法撤销 " ) if @shixun . status == 2
apply = ApplyAction . where ( :container_type = > " ApplyShixun " , :container_id = > @shixun . id ) . order ( " created_at desc " ) . first
if apply && apply . status == 0
apply . update_attribute ( :status , 3 )
apply . tidings . destroy_all
end
tip_exception ( " 请先撤销申请公开,再撤销发布 " ) if @shixun . public == 1
tip_exception ( " 实训已经公开,无法撤销 " ) if @shixun . public == 2
@shixun . update_column ( :status , 0 )
end
@ -1004,4 +1139,48 @@ private
ShixunSecretRepository . create! ( repo_name : repo_path . split ( " . " ) [ 0 ] , shixun_id : @shixun . id )
end
def file_save_to_local ( save_path , temp_file , ext )
unless Dir . exists? ( save_path )
FileUtils . mkdir_p ( save_path ) ##不成功这里会抛异常
end
digest = md5_file ( temp_file )
digest = " #{ digest } _ #{ ( Time . now . to_f * 1000 ) . to_i } "
local_file_path = File . join ( save_path , digest ) + ext
save_temp_file ( temp_file , local_file_path )
[ local_file_path , digest ]
end
def save_temp_file ( temp_file , save_file_path )
File . open ( save_file_path , 'wb' ) do | f |
temp_file . rewind
while ( buffer = temp_file . read ( 8192 ) )
f . write ( buffer )
end
end
end
def file_ext ( file_name )
ext = ''
exts = file_name . split ( " . " )
if exts . size > 1
ext = " . #{ exts . last } "
end
ext
end
def delete_file ( file_path )
File . delete ( file_path ) if File . exist? ( file_path )
end
def md5_file ( temp_file )
md5 = Digest :: MD5 . new
temp_file . rewind
while ( buffer = temp_file . read ( 8192 ) )
md5 . update ( buffer )
end
md5 . hexdigest
end
end