trustieplus/app/controllers/shixuns_controller.rb

1013 lines
39 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# encoding: utf-8
# REDO: 创建版本库权限控制
class ShixunsController < ApplicationController
layout 'base_shixun'
before_filter :require_login, :except => [:ghook]
before_filter :check_authentication, :except => [:ghook]
before_filter :find_shixun, :except => [ :index, :new, :create, :index, :search, :shixun_courses, :new_disscuss, :shixun_migrate]
skip_before_filter :verify_authenticity_token, :only => [:ghook]
before_filter :shixun_view_allow, :only => [:show]
before_filter :require_manager, :only => [ :settings, :add_script, :publish, :collaborators_delete, :shixun_members_added, :add_collaborators]
before_filter :validation_email, :only => [:new]
include ApplicationHelper
CODES = %W(2 3 4 5 6 7 8 9 A B C D E F G H J K L N M O P Q R S T U V W X Y Z)
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)
# 获取版本库文件目录
def search_file_list
path = params[:path]
@path = to_path_param(path)
g = Gitlab.client
@dir = g.trees(@shixun.gpid, :path => @path).map{|tree|[tree.type, (@path.blank? ? tree.name : "#{@path}"+"/"+tree.name )]}
logger.info("dir is ##{@dir}")
respond_to do |format|
format.js
end
# render :json => {:dir => @dir}
end
def achieve_ways
@repository = @shixun.repository
@entries = @repository.entries(@path, @rev)
# @entries = Gitlab.client.trees(@shixun.gpid).map{|tree| tree.name}
end
def statistics_students
pub_shixun = ApplyAction.where(:container_type => "ApplyShixun", :status => 1, :container_id => @shixun.id).last
if pub_shixun.present?
updated_at = pub_shixun.updated_at
@statistics = @shixun.myshixuns.select{|myshixun| myshixun.updated_at > updated_at}
@statistics = @statistics.map(&:id)
@statistics = Myshixun.where(:id => @statistics).order("created_at desc")
#@statistics = @shixun.myshixuns.where("created_at > #{updated_at}").order("created_at desc")
@statistics_count = @statistics.count
@limit = 15
@is_remote = true
@statistic_pages = Paginator.new @statistics_count, @limit, params['page'] || 1
@offset ||= @statistic_pages.offset
@statistics = paginateHelper @statistics, @limit
end
end
# push代码的时候会触发gitlab hook
def ghook
# shixun_modify_status_without_publish(@shixun, 1)
render :json => {status: "success"}
end
# 注意shixun_id 格式 /shixun_migrate?shixun_id=100
# 注意language 格式 /shixun_migrate?language="Java,Python"
def shixun_migrate
unless User.current.admin?
render_403
return
end
shixun_tomcat = Redmine::Configuration['shixun_tomcat']
if params[:language]
language = params[:language].split("/")
logger.info(language)
shixuns = Shixun.where(:language => language)
elsif params[:shixun_id]
shixuns = Shixun.where(:id => params[:shixun_id])
else
shixuns = Shixun.all
end
if shixuns.present?
shixuns.each do |shixun|
begin
logger.info("shixun id is #{shixun.id}")
tpiList =[]
gameInfo = shixun.gameInfo
myshixuns = shixun.myshixuns
if myshixuns.present?
myshixuns.each do |myshixun|
logger.info("tpiID is #{myshixun.id}")
tpiID = myshixun.id
instanceGitURL = git_myshixun_url_ip(myshixun, myshixun.try(:user_id))
logger.info("instanceGitURL is #{instanceGitURL}")
tpiList << {:tpiID => tpiID, :instanceGitURL => instanceGitURL}
logger.info("###############{tpiList.to_json unless tpiList.blank?}")
logger.info("************#{tpiList}")
end
end
tpiList = Base64.urlsafe_encode64(tpiList.to_json) unless tpiList.blank?
params = {:gameInfo => "#{gameInfo}", :tpiList => "#{tpiList}" }
logger.info("params is #{params}")
uri = "#{shixun_tomcat}/bridge/dataTransfer/transfer"
logger.info("uri is #{uri}")
res = uri_exec uri, params
logger.info("=====res is #{res['code']}")
render :json => {:result => "success"}
rescue Exception => e
logger.info("error ====> #{e.message}")
end
end
end
end
def shixun_test
jenkins_shixuns = Redmine::Configuration['jenkins_shixuns']
uri = URI("#{jenkins_shixuns}/jenkins-exec/webssh/getConnectInfo")
user_id = User.current.id
params = {userID:user_id}
res = uri_exec uri, params
render :json => {data:"succesed"}
end
def delete_shixun_test
jenkins_shixuns = Redmine::Configuration['jenkins_shixuns']
uri = URI("#{jenkins_shixuns}/jenkins-exec/webssh/deleteSSH")
user_id = User.current.id
params = {userID:user_id}
res = uri_exec uri, params
render :json => {data:"succesed"}
end
def game_webssh
end
def entry_edit
g = Gitlab.client
@path = params[:path]
@rev = params[:rev]
file_content = g.files(@shixun.gpid, @path, @rev).content
@content = tran_base64_decode64(file_content)
respond_to do |format|
format.js
end
end
def entry_update
g = Gitlab.client
@path = params[:path]
@rev = params[:rev]
@content = params[:content]
code_file = g.edit_file(@shixun.gpid, :content => params[:content], :file_path => @path, :branch_name => @rev, :commit_message => "shixun entry")
# if @shixun.try(:status).to_i < 2
# shixun_modify_status_without_publish(@shixun, 1)
# end
respond_to do |format|
format.js
end
end
def shixun_monitor
# monitor_filter
# if @had_exec
# @tpm = Myshixun.where(:user_id => User.current, :shixun_id => @shixun).first
# end
#
# respond_to do |format|
# format.js
# end
end
def statistics
@challenges = @shixun.challenges
@top_students = @shixun.myshixuns.where(:status => 1)
myshixuns = @shixun.myshixuns.includes(:games)
@latest_myshixuns = myshixuns.order("created_at desc").limit(4)
end
def autocompletion
end
def index
@order = "myshixun_count"
@sort = "asc"
search = params[:search]
@mail = User.current.mail.blank?
@shixun_all_count = Shixun.where(:hidden => 0).count
@shixuns = Shixun.where("name like ? and hidden = 0", "%#{search}%")
# @shixuns.each do |shixun|
# shixun[:myshixunCount] = shixun.myshixuns.count
# end
# @shixuns = @shixuns.sort{|x, y| y[:myshixunCount] <=> x[:myshixunCount]}
@shixuns = @shixuns.select("shixuns.*, (select count(myshixuns.id) from myshixuns where myshixuns.shixun_id = shixuns.id group by shixuns.id) AS myshixunCount").reorder("status = 2 desc, myshixunCount desc")
@shixun_my_score = Experience.find_by_sql("SELECT sum(score) as score FROM `experiences` where user_id=#{User.current.id}").first.try(:score).to_i
@current_user_had_passed = Myshixun.find_by_sql("select count(*) as had_passed from myshixuns where status =1 and user_id=#{User.current.id}
and shixun_id in (SELECT id FROM `shixuns` where status > 1)").first.try(:had_passed).to_i
#@majors = Major.where(:id => [635, 636, 637, 638, 639, 622, 619])
@courses = CourseList.where(:support_shixuns_search => 1)
@shixuns_count = @shixuns.count
@limit = 16
@is_remote = true
@shixun_pages = Paginator.new @shixuns_count, @limit, params['page'] || 1
@offset ||= @shixun_pages.offset
@shixuns = paginateHelper @shixuns, @limit
render :layout => "base_edu"
end
def propaedeutics
respond_to do |format|
format.html
end
end
def update_propaedeutics
@shixun = Shixun.where(:identifier => params[:id]).first
@shixun.update_attribute("propaedeutics", params[:shixun][:propaedeutics])
redirect_to propaedeutics_shixun_path(@shixun)
end
def collaborators
@collaborators = @shixun.collaborators
end
def collaborators_delete
user_id = params[:c_id]
gid = User.find(user_id).try(:gid)
shixun_member = ShixunMember.where(:user_id => user_id, :shixun_id => @shixun.id, :role => 2).first
shixun_member.delete
g = Gitlab.client
unless gid.nil?
g.remove_team_member(@shixun.gpid, gid)
end
@collaborators = @shixun.collaborators
respond_to do |format|
format.js
end
end
# 已存在的成员不添加
def add_collaborators
if !params[:search].nil?
# members = searchTeacherAndAssistant @course
member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")"
condition = "%#{params[:search].strip}%".gsub(" ","")
@users = User.where("id not in #{member_ids} and status = 1 and LOWER(concat(lastname, firstname, login, mail)) LIKE '#{condition}'").includes(:user_extensions)
end
respond_to do |format|
format.js
end
end
# 事务处理保证Trustie与Gitlab数据同步
def shixun_members_added
ActiveRecord::Base.transaction do
begin
unless params[:membership][:user_ids].blank?
memberships = params[:membership][:user_ids]
memberships.each do |member|
user = User.find(member)
s = Trustie::Gitlab::Sync.new
if user.gid.present?
gid = user.gid
else
guser = s.sync_user(user)
gid = guser.id
end
ShixunMember.create!(:user_id => member, :shixun_id => @shixun.id, :role => 2)
u = s.g.add_team_member(@shixun.gpid, gid, 40) # 3代表角色master
if u.blank?
raise("同步Gitlab数据失败")
end
end
@collaborators = @shixun.collaborators
respond_to do |format|
format.js
end
end
rescue Exception => e
logger.error(e)
raise ActiveRecord::Rollback
end
end
end
def search
# 确定 sort 1升序 2 降序
@order = params[:order] || "myshixun_count"
bsort = params[:sort] || "desc"
@sort = bsort == "asc" ? "desc" : "asc"
if @order == "updated_at"
order_str = "#{Shixun.table_name}.updated_at #{@sort}"
else
order_str = "myshixun_count #{bsort}, #{Shixun.table_name}.updated_at #{bsort}"
end
@language = params[:language]
@status = params[:status].to_i
@shixun_status = params[:shixun_status] # 2是已发布 3是未发布
@search = params[:search]
#@major = params[:major]
@course = params[:course]
@trainee = params[:trainee]
#ids = Shixun.find_by_sql("select group_concat(id) as allId from shixuns where id in (SELECT distinct(shixun_id) FROM `challenges`)")
# @shixuns = Shixun.where("hidden = 0").reorder("updated_at desc")
@shixuns = Shixun.where("hidden = 0")
@shixuns = @shixuns.where(:language => @language) unless @language.blank?
@shixuns = @shixuns.where("name like ?", "%#{@search}%") unless @search.blank?
# if !@major.blank?
# @shixuns = @shixuns.where(:major_id => @major.to_i)
# @courses = CourseList.where(:id => MajorCourse.where(:major_id => @major).map(&:course_list_id))
# else
# @courses = CourseList.where(:id => MajorCourse.where(:major_id => [635, 636, 637, 638, 639, 622, 619]).map(&:course_list_id))
# end
@courses = CourseList.where(:support_shixuns_search => 1)
#if !@course.blank? && (@major.blank? || MajorCourse.where(:major_id => @major, :course_list_id => @course).count == 1)
if !@course.blank?
@shixuns = @shixuns.where(:id => ShixunMajorCourse.where(:course_list_id => @course).map(&:shixun_id))
end
# if !@major.blank? && MajorCourse.where(:major_id => @major, :course_list_id => @course).count == 0
# @course = nil
# end
@shixuns = @shixuns.where(:trainee => @trainee) unless @trainee.blank?
case @status
when 1, 0
@shixuns = @shixuns
when 2
@shixuns = @shixuns.where(:user_id => User.current)
when 3
shixun_ids = Myshixun.where(:user_id => User.current).blank? ? "(-1)" : "(" + Myshixun.where(:user_id => User.current).map(&:shixun_id).join(',') +")"
@shixuns = @shixuns.where("id not in #{shixun_ids}")
when 4
shixun_ids = Myshixun.where(:user_id => User.current, :status => 0).map(&:shixun_id)
@shixuns = @shixuns.where(:id => shixun_ids)
when 5
shixun_ids = Myshixun.where(:user_id => User.current, :status => 1).map(&:shixun_id)
@shixuns = @shixuns.where(:id => shixun_ids)
end
case @shixun_status
when "1"
@shixuns = @shixuns.where(:status => [0, 1])
when "2"
@shixuns = @shixuns.where(:status => 2)
when "3"
@shixuns = @shixuns.where(:status => 3)
when nil, "0"
@shixuns = @shixuns
end
if @order == "updated_at"
@shixuns =@shixuns.reorder(order_str)
else
# 最热排序
# @shixuns.each do |shixun|
# shixun[:myshixunCount] = shixun.myshixuns.count
# end
@shixuns = @shixuns.select("shixuns.*, (select count(myshixuns.id) from myshixuns where myshixuns.shixun_id = shixuns.id group by shixuns.id) AS myshixunCount").reorder("status = 2 desc, myshixunCount #{bsort}")
#@shixuns = @shixuns.reorder("status = 2 #{bsort}, myshixunCount #{bsort}")
# if bsort == "desc"
# @shixuns = @shixuns.sort{|x, y| y[:myshixunCount] <=> x[:myshixunCount]}
# else
# @shixuns = @shixuns.sort{|x, y| x[:myshixunCount] <=> y[:myshixunCount]}
# end
end
# @shixuns = Shixun.where(:authentication => 1).reorder(order)
@shixuns_count = @shixuns.count
@limit = 16
@is_remote = true
@shixun_pages = Paginator.new @shixuns_count, @limit, params['page'] || 1
@offset ||= @shixun_pages.offset
@shixuns = paginateHelper @shixuns, @limit
respond_to do |format|
format.js
end
end
# jenkins回调脚本
# gameID 及实训ID
def publish
@status = 0
@position = ""
begin
@shixun.challenges.each do |challenge|
if challenge.challenge_tags.count == 0
@status = 2
@position = (@position == "" ? @position : (@position + "")) + challenge.position.to_s + ""
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 => User.current.id, :status => 0)
notes = User.current.show_name.to_s + " 申请发布实训:<a href='#{shixun_path(@shixun)}'>#{@shixun.name}</a>"
JournalsForMessage.create(:jour_id => 1, :jour_type => 'Principal', :user_id => User.current.id, :notes => notes, :private => 1, :reply_id => 0)
@status = 1
end
end
rescue Exception => e
@jenkin_error = true
logger.error("pushlish game #{e}")
respond_to do |format|
format.js
end
end
end
def apply_publish
apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).last
if apply && apply.status == 0
@status = 0
else
ApplyAction.create(:container_type => "ApplyShixun", :container_id => @shixun.id, :user_id => User.current.id, :status => 0)
notes = User.current.show_name.to_s + " 申请发布实训:<a href='#{shixun_path(@shixun)}'>#{@shixun.name}</a>"
JournalsForMessage.create(:jour_id => 1, :jour_type => 'Principal', :user_id => User.current.id, :notes => notes, :private => 1, :reply_id => 0)
@shixun.update_column('status', 1)
@status = 1
end
end
def cancel_publish
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)
@shixun.update_column('status', 0)
end
redirect_to shixun_path(@shixun)
end
def close
@shixun.update_column('status', 3)
redirect_to shixun_path(@shixun)
end
# copy_shixun复制一个新的实训模块包括版本库
# copy_myshixun自动创建系列game,game中只包含状态等信息公共信息从Challeges中读取
# 开启过实训的则直接跳入my实训页面
def shixun_exec
unless allow_shixun_exec(@shixun) && (User.current.manager_of_shixun?(@shixun) || @shixun.status > 0)
render_403
return
end
myshixun = Myshixun.where(:user_id => User.current.id, :shixun_id => @shixun.id).first
unless myshixun.blank?
logger.info("current task id is #{myshixun.current_task}")
redirect_to myshixun_game_path(myshixun.current_task, :myshixun_id => myshixun, :is_subject => params[:is_subject])
return
end
ActiveRecord::Base.transaction do
begin
shixun_tomcat = Redmine::Configuration['shixun_tomcat']
code = down_generate_identifier("myshixun")
myshixun = Myshixun.create!(:shixun_id => @shixun.id, :user_id => User.current.id, :identifier => code)
# fork版本库如果用户没有同步则先同步用户
g = Gitlab.client
if User.current.gid.nil?
s = Trustie::Gitlab::Sync.new
s.sync_user(User.current)
end
gshixun = g.fork(@shixun.gpid, User.current.gid)
if gshixun.try(:id).present?
myshixun.update_column(:gpid, gshixun.id) if myshixun.try(:gpid).blank?
# educoder 加入到myshixun中
myshixun_admin_gid = User.where(:login => "educoder").first.try(:gid)
g.add_team_member(gshixun.id, myshixun_admin_gid, 40) # 30代表角色master
commit_id = g.commits(@shixun.gpid).first.try(:id)
myshixun.update_column(:commit_id, commit_id)
rep = Repository.create!(:myshixun_id => myshixun.id, :identifier => gshixun.name,:project_id => -1, :shixun_id => -2)
rep.update_column(:type, "Repository::Gitlab")
rep_url = Base64.urlsafe_encode64(git_shixun_url_ip @shixun, (@shixun.try(:fork_from).blank? ? "educoder" : "eduforge")) # 注意educoder为默认给实训创建版本库的用户如果换成别的用户名字要相应的修改
logger.info("start openGameInstance")
uri = "#{shixun_tomcat}/bridge/game/openGameInstance"
logger.info("end openGameInstance")
params = {tpiID: "#{myshixun.id}", tpmID: "#{@shixun.id}", instanceGitURL:rep_url, operationEnvironment:"#{@shixun.try(:language)}"}
logger.info("openGameInstance params is #{params}")
res = uri_exec uri, params
if (res && res['code'].to_i != 0)
raise("实训云平台繁忙繁忙等级83")
end
# 其它操作
challenges = @shixun.challenges
# 之所以增加user_id是为了方便统计查询性能
challenges.each_with_index do |challenge, index|
status = (index == 0 ? 0 : 3)
code = down_generate_identifier("game")
game =Game.create!(:challenge_id => challenge.id, :myshixun_id => myshixun.id, :status => status, :user_id => myshixun.user_id, :open_time => Time.now, :identifier => code)
# 记录刚开始时默认代开文件原始代码
# 刚开始fork的一段时间是获取不了content内容的
game_passed_code(game.try(:id), challenge.try(:path), myshixun.try(:gpid), 0)
end
if params[:type] == "1" # 重置过来的请求
shixun_mod = ShixunModify.where(:shixun_id => myshixun.try(:shixun_id), :myshixun_id => myshixun.try(:id)).first
if shixun_mod.nil?
ShixunModify.create(:shixun_id => myshixun.shixun_id, :myshixun_id => myshixun.id, :status => 0)
else
shixun_mod.update_attributes(:status => 0)
end
end
else
raise("实训云平台繁忙繁忙等级81")
end
logger.info("myshixun id si #{myshixun.id} and current_task id is#{myshixun.current_task.id}")
redirect_to myshixun_game_path(myshixun.current_task, :myshixun_id => myshixun, :is_subject => params[:is_subject])
rescue Exception => e
flash[:error] = e.message
logger.info("failed to exec shixun: current task id is #{e}")
g.delete_project(gshixun.id) if !gshixun.id.nil?
redirect_to shixun_challenges_path(@shixun)
raise ActiveRecord::Rollback
end
end
end
def shixun_courses
data = {result:0,options:[]}
if params[:major_id] != 0
major = Major.find params[:major_id]
if major
data[:result] = 1
major_courses = major.major_courses
CourseList.where(:id => major_courses.map(&:course_list_id)).each do |course|
option = []
option << course.name.to_s
option << course.id
data[:options] << option
end
else
data[:result] = 0
end
else
data[:result] = 0
end
render :json =>data
end
def new
@shixun = Shixun.new
@support = Major.where(:support_shixuns=> 1)
respond_to do |format|
format.html{render :layout => 'base_edu'}
format.json
end
end
def create
identifier = generate_identifier
@shixun = Shixun.new(params[:shixun])
@shixun.user_id = User.current.id
@shixun.language = params[:language]
#@shixun.major_id = params[:major_id]
@shixun.trainee = params[:trainee]
@shixun.webssh = params[:webssh].to_i
@shixun.can_copy = params[:can_copy].to_i
@shixun.identifier = identifier
# if params[:course_id]
# params[:course_id].each do |course_id|
# @shixun.shixun_major_courses << ShixunMajorCourse.new(:major_id => params[:major_id], :course_list_id => course_id)
# end
# end
if CourseList.where(:name => params[:course_list].strip).count > 0
@shixun.shixun_major_courses << ShixunMajorCourse.new(:major_id => -1, :course_list_id => CourseList.where(:name => params[:course_list].strip).first.id)
else
course_list = CourseList.create(:name => params[:course_list].strip, :user_id => User.current.id, :is_admin => 0)
@shixun.shixun_major_courses << ShixunMajorCourse.new(:major_id => -1, :course_list_id => course_list.id)
end
(params[:shixun][:is_public] == "1" ? @shixun.is_public = true : @shixun.is_public = false)
ActiveRecord::Base.transaction do
begin
@shixun.save!
m = ShixunMember.new(:user_id => User.current.id, :role => 1)
@shixun.shixun_members << m
# 自动构建版本库
repository = Repository.new
repository.shixun = @shixun
repository.type = 'Repository::Gitlab'
repository.identifier = @shixun.identifier.downcase
repository.project_id = -1
repository.save!
s = Trustie::Gitlab::Sync.new
gproject = s.create_shixun(@shixun, repository)
raise "版本库创建失败" if @shixun.gpid.blank? # 若和gitlab没同步成功则抛出异常
# g = Gitlab.client
# hook_url = Setting.protocol + "://" + Setting.host_name + "/shixuns/#{@shixun.identifier}" + "/ghook"
# g.add_project_hook(@shixun.gpid, hook_url)
redirect_to shixun_path @shixun, notice: l(:notice_successful_create)
rescue Exception => e
respond_to do |format|
flash[:notice] = "#{e.message}"
redirect_to new_shixun_path
raise ActiveRecord::Rollback
end
end
end
end
def copy
unless (@shixun.can_copy && User.current.user_extensions.try(:identity) == 0 && User.current.professional_certification)
render_403
return
end
ActiveRecord::Base.transaction do
begin
new_shixun = Shixun.new
new_shixun.attributes = @shixun.attributes.dup.except("id","user_id","visits","gpid","status", "identifier", "homepage_show")
new_shixun.user_id = User.current.id
new_shixun.identifier = generate_identifier
new_shixun.status = 0
new_shixun.fork_from = @shixun.id
new_shixun.save!
shixun_major_courses = ShixunMajorCourse.where(:shixun_id => @shixun.id)
if shixun_major_courses.present?
shixun_major_courses.each do |smc|
ShixunMajorCourse.create!(:shixun_id => new_shixun.id, :major_id => smc.major_id, :course_list_id => smc.course_list_id)
end
end
# 同步复制版本库先fork再修改版本库名
# eduforge用户作为版本库的创建者
repository = Repository.new
repository.shixun = new_shixun
repository.type = 'Repository::Gitlab'
repository.identifier = new_shixun.identifier.downcase
repository.project_id = -1
repository.save!
g = Gitlab.client
user_gid = User.find_by_mail("eduforge@163.com").try(:gid)
gshixun = g.fork(@shixun.gpid, user_gid)
raise "版本库创建失败" if gshixun.try(:id).blank?
#gshixun = g.edit_project(gshixun.id, new_shixun.identifier, new_shixun.identifier)
raise "实训复制失败" if (gshixun.try(:name) != new_shixun.identifier || gshixun.try(:path) != new_shixun.identifier)
new_shixun.update_column(:gpid, gshixun.id)
# 同步复制者至gitlab,必须要求用户绑定了邮箱
ShixunMember.create!(:user_id => User.current.id, :shixun_id => new_shixun.try(:id), :role => 1)
s = Trustie::Gitlab::Sync.new
gid = User.current.try(:gid)
u = g.add_team_member(gshixun.id, gid, 40) # 3代表角色master
# # 同步复制合作者,合作者加入到gitlab
# unless User.current.manager_of_shixun?(@shixun)
# ShixunMember.create!(:user_id => User.current.id, :shixun_id => new_shixun.try(:id), :role => 1)
# end
# @shixun.shixun_members.each do |shixun_member|
# if ShixunMember.where(:shixun_id => new_shixun.try(:id), :user_id => shixun_member.user_id).blank?
# ShixunMember.create!(:user_id => shixun_member.try(:user_id), :shixun_id => new_shixun.try(:id),
# :role => (shixun_member.try(:user_id) == User.current.id ? 1 : 2))
# end
# s = Trustie::Gitlab::Sync.new
# gid = User.find(shixun_member.user_id).try(:gid)
# u = s.g.add_team_member(gshixun.id, gid, 40) # 3代表角色master
# if u.blank?
# raise("同步Gitlab数据失败")
# end
# end
# 同步复制关卡
if @shixun.challenges.present?
@shixun.challenges.each do |challenge|
new_challenge = Challenge.new
new_challenge.attributes = challenge.attributes.dup.except("id","shixun_id","user_id")
new_challenge.user_id = User.current.id
new_challenge.shixun_id = new_shixun.id
new_challenge.save!
if challenge.st == 0 # 评测题
# 同步测试集
if challenge.test_sets.present?
challenge.test_sets.each do |test_set|
new_test_set = TestSet.new
new_test_set.attributes = test_set.attributes.dup.except("id","challenge_id")
new_test_set.challenge_id = new_challenge.id
new_test_set.save!
end
end
# 同步关卡标签
challenge_tags = ChallengeTag.where("challenge_id =? and challenge_choose_id is null", challenge.id)
if challenge_tags.present?
challenge_tags.each do |challenge_tag|
ChallengeTag.create!(:challenge_id => new_challenge.id, :name => challenge_tag.try(:name))
end
end
elsif challenge.st == 1 # 选择题
if challenge.challenge_chooses.present?
challenge.challenge_chooses.each do |challenge_choose|
new_challenge_choose = ChallengeChoose.new
new_challenge_choose.attributes = challenge_choose.attributes.dup.except("id","challenge_id")
new_challenge_choose.challenge_id = new_challenge.id
new_challenge_choose.save!
# 每一题的选项
if challenge_choose.challenge_questions.present?
challenge_choose.challenge_questions.each do |challenge_question|
new_challenge_question = ChallengeQuestion.new
new_challenge_question.attributes = challenge_question.attributes.dup.except("id","challenge_choose_id")
new_challenge_question.challenge_choose_id = new_challenge_choose.id
new_challenge_question.save!
end
end
# 每一题的知识标签
st_challenge_tags = ChallengeTag.where(:challenge_id => challenge.id, :challenge_choose_id => challenge_choose.id)
if st_challenge_tags.present?
st_challenge_tags.each do |st_challenge_tag|
ChallengeTag.create!(:challenge_id => new_challenge.id, :name => st_challenge_tag.try(:name), :challenge_choose_id => new_challenge_choose.id)
end
end
end
end
end
end
end
# 中间层创建测试集
shixun_tomcat = Redmine::Configuration['shixun_tomcat']
gameInfo = new_shixun.gameInfo
uri ="#{shixun_tomcat}/bridge/game/publishGame"
params = {gameInfo:gameInfo}
res = uri_exec uri, params
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级90")
end
flash[:notice] = "实训复制成功"
redirect_to shixun_challenges_path(new_shixun)
rescue Exception => e
logger.info("copy shixun failed ##{e.message}")
flash[:notice] = "#{e.message}"
g.delete_project(gshixun.id) if gshixun.try(:id).present? # 异常后,如果已经创建了版本库需要删除该版本库
redirect_to shixun_challenges_path(@shixun)
raise ActiveRecord::Rollback
end
end
end
def fork_list
@shixuns = Shixun.where(:fork_from => @shixun.id)
@shixuns_count = @shixuns.count
@limit = 16
@is_remote = true
@shixun_pages = Paginator.new @shixuns_count, @limit, params['page'] || 1
@offset ||= @shixun_pages.offset
@shixuns = paginateHelper @shixuns, @limit
end
def show
respond_to do |format|
format.html{redirect_to shixun_challenges_path(@shixun)}
end
end
def generate_identifier
code = DCODES.sample(8).join
return generate_identifier if Shixun.where(identifier: code).present?
code
end
def down_generate_identifier type
if type == "game"
code = DCODES.sample(12).join
return down_generate_identifier(type) if Game.where(identifier: code).present?
elsif type == "myshixun"
code = DCODES.sample(10).join
return down_generate_identifier(type) if Myshixun.where(identifier: code).present?
end
code
end
def edit
end
def update
language = @shixun.language
@shixun.attributes = params[:shixun]
@shixun.language = params[:language]
@shixun.trainee = params[:trainee]
@shixun.webssh = params[:webssh].to_i
@shixun.can_copy = params[:can_copy].to_i
# if params[:course_id]
# @shixun.shixun_major_courses.destroy_all
# params[:course_id].each do |course_id|
# @shixun.shixun_major_courses << ShixunMajorCourse.new(:major_id => params[:major_id], :course_list_id => course_id)
# end
# end
# @shixun.major_id = params[:major_id]
@shixun.shixun_major_courses.destroy_all
course_lists = params[:course_list].strip.split(",")
course_lists.each do |course|
if CourseList.where(:name => course).count > 0
@shixun.shixun_major_courses << ShixunMajorCourse.new(:major_id => -1, :course_list_id => CourseList.where(:name => course.strip).first.id)
else
course_list = CourseList.create(:name => course.strip, :user_id => User.current.id, :is_admin => 0)
@shixun.shixun_major_courses << ShixunMajorCourse.new(:major_id => -1, :course_list_id => course_list.id)
end
end
params[:shixun][:is_public] == "on" ? @shixun.is_public = 1 : @shixun.is_public = 0
ActiveRecord::Base.transaction do
begin
@shixun.save!
if language != params[:language] && @shixun.status != 2 # 已发布不触发重置
add_shixun_modify_status(@shixun, 1)
end
rescue
@error = "实训保存失败"
raise ActiveRecord::Rollback
end
respond_to do |format|
format.js
end
end
end
def shixun_discuss
@discusses = @shixun.discusses.reorder("created_at desc")
@discusses_count = @discusses.count
#@limit = 15
#@is_remote = true
#@discusses_pages = Paginator.new @discusses_count, @limit, params['page'] || 1
# @offset ||= @discusses_pages.offset
#@discusses = paginateHelper @discusses, @limit
#@game_challenge = params[:challenge_id].blank? ? Challenge.find(@discusses.challenge_id) : Challenge.find(params[:challenge_id])
challenge_id = params[:challenge_id].nil? ? @shixun.challenges.first.try(:id) : params[:challenge_id].to_i
@game_challenge = Challenge.find(challenge_id)
respond_to do |format|
format.js
format.html
end
end
def destroy
unless User.current.admin?
render_403
return
end
Subject.where(:id => @shixun.stage_shixuns.map(&:subject_id)).destroy_all
g = Gitlab.client
g.delete_project(@shixun.gpid) if @shixun.try(:gpid).present?
@shixun.destroy
respond_to do |format|
format.html{ redirect_to shixuns_managements_path }
format.js
end
end
def settings
@repository = Repository.where(:shixun_id => @shixun, :type => "Repository::Gitlab").first
unless @repository.nil?
gitlab_address = Redmine::Configuration['gitlab_address']
login = User.find_by_mail("educoder@163.com").try(:login)
@repos_url = git_shixun_url(@shixun, login)
end
end
# 添加实训脚本
def add_script
if @shixun.update_attribute(:script, params[:shixun_script])
@notice = "脚本添加成功"
else
@notice = "脚本添加失败"
end
end
# 创建实训job
def shixun_job_create
if @shixun.challenges.count == 0
@notice = "实训开启失败:请先发布实训任务"
return
elsif Repository.where(:shixun_id => @shixun.id, :type => "Repository::Gitlab").count == 0
@notice = "实训开启失败:请先创建版本库"
return
end
@shixun.update_attribute(:status, 1)
end
# 更新实训job
def shixun_job_update
# jobName = "#{@shixun.id}"
# pipeLine = "#{Base64.encode64(@shixun.script)}"
# uri = URI("http://123.59.135.74:9999/jenkins-exec/api/updateJob")
# params = {jobName: jobName, pipeLine: pipeLine}
# res = uri_exec uri, params
training_shixun_notice res
if res['code'] == 0
@shixun.update_attribute(:status, 1)
end
end
# Find shixun of id params[:id]
def find_shixun
@shixun = Shixun.find_by_identifier(params[:id])
render_404 if @shixun.nil?
rescue ActiveRecord::RecordNotFound
render_404
end
def monitor_filter
if User.current.id == @shixun.user_id
@notice = l(:label_shixun_mine)
else
if has_exec_cur_shixun(@shixun)
@notice = l(:label_shixun_had_forked)
@had_exec = true
else
@notice = l(:label_shixun_exec)
@had_exec = false
end
end
end
# 实训行为操作
def operation
@is_subject = params[:is_subject]
@myshixun = Myshixun.where(:id => params[:myshixun_id]).first
@is_modify = ShixunModify.where(:myshixun_id => params[:myshixun_id], :shixun_id => @shixun.try(:id), :status => 1).first
@mail = User.current.mail.blank?
end
# 实训的发送至课堂:搜索课堂
def search_user_courses
@user = User.current
if !params[:search].nil?
search = "%#{params[:search].to_s.strip.downcase}%"
@courses = @user.courses.not_deleted_not_end.where("#{Course.table_name}.name like :p",:p=>search).select{|course| @user.has_teacher_role(course)}
else
@courses = @user.courses.not_deleted_not_end.select{|course| @user.has_teacher_role(course)}
end
@pages = Paginator.new @courses.count, 8, params['page'] || 1
@offset ||= @pages.offset
@courses = paginateHelper @courses, 8
respond_to do |format|
format.js
end
end
# 将实训发送到课程
def send_to_course
homework = HomeworkCommon.new
homework.name = @shixun.name
homework.description = @shixun.description
homework.anonymous_comment = 1
homework.homework_type = 4
homework.late_penalty = 0
homework.teacher_priority = 1
homework.user_id = User.current.id
homework.course_id = params[:course]
homework_detail_manual = HomeworkDetailManual.new
homework_detail_manual.te_proportion = 1.0
homework_detail_manual.ta_proportion = 0
homework_detail_manual.comment_status = 0
homework_detail_manual.evaluation_num = 0
homework_detail_manual.absence_penalty = 0
homework.homework_detail_manual = homework_detail_manual
if homework.save!
homework_detail_manual.save if homework_detail_manual
HomeworkCommonsShixuns.create(:homework_common_id => homework.id, :shixun_id => @shixun.id)
redirect_to setting_homework_common_path(homework, :is_new => 1)
end
end
private
# REDO: 新增类型copy的时候
# 复制项目
# gshixun --> gitlab project
# CODES = %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)
def copy_myshixun shixun, gshixun
myshixun = Myshixun.new
# myshixun.attributes = shixun.attributes.dup.except("id","user_id","visits","gpid","status", "identifier","propaedeutics")
myshixun.shixun_id = shixun.id
myshixun.user_id = User.current.id
myshixun.gpid = gshixun.id
shixun_tomcat = Redmine::Configuration['shixun_tomcat']
if myshixun.save!
# 为了避免fork多次的问题
if gshixun.try(:name).include?("-")
logger.info("***** gshixun name is #{gshixun.try(:name)}")
@g.delete_project(gshixun.id)
gshixun = @g.project(myshixun.gpid)
myshixun.update_column(:gpid, gshixun.id)
end
code = down_generate_identifier("myshixun")
myshixun.update_attribute(:identifier, code)
rep = Repository.new(:myshixun_id => myshixun.id, :identifier => gshixun.name,:project_id => -1, :shixun_id => -2)
rep.type = "Repository::Gitlab"
rep.save!
login = User.find_by_mail("educoder@163.com").try(:login)
rep_url = Base64.urlsafe_encode64(git_shixun_url_ip shixun, login)
uri = "#{shixun_tomcat}/bridge/game/openGameInstance"
params = {tpiID: "#{myshixun.id}", tpmID: "#{shixun.id}", instanceGitURL:rep_url, operationEnvironment:"#{shixun.try(:language)}"}
logger.info("openGameInstance params is #{params}")
res = uri_exec uri, params
if (res && res['code'].to_i != 0)
raise("实训云平台繁忙繁忙等级83")
end
return myshixun
end
end
def training_shixun_notice res
if res['code'] == 0
@notice = "实训开启成功"
else
@notice = res['msg'].nil? ? "实训开启失败" : res['msg']
end
end
# 权限控制
def shixun_view_allow
render_403 if (@shixun.status == 0 && !(User.current.manager_of_shixun?(@shixun) || User.current.admin?))
end
# 实训管理员或者超级管理员
def require_manager
render_403 unless (User.current.manager_of_shixun?(@shixun) || User.current.admin?)
end
def validation_email
render_403 if User.current.mail.blank?
end
end