# encoding: utf-8
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Time 2015-01-28 16:34:21
# Author lizanle
# Description 封装代码,简化代码,格式化代码,
class ProjectsController < ApplicationController
layout 'base_projects'
before_filter :authorize1 , :only = > [ :show ]
# menu_item :overview, :only => :show
# menu_item :roadmap, :only => :roadmap
# menu_item :settings, :only => :settings
# menu_item :homework, :only => [:homework, :new_homework]
# menu_item :feedback, :only => :feedback
# menu_item :share, :only => :share
skip_before_filter :verify_authenticity_token , :only = > [ :training_task_status ]
skip_before_filter :check_if_login_required , :only = > [ :training_task_status ]
before_filter :local_exam
before_filter :check_authentication
before_filter :find_project , :except = > [ :index , :search , :list , :new , :create , :copy , :statistics , :new_join , :course , :enterprise_course , :course_enterprise ,
:view_homework_attaches , :join_project , :project_home , :training_execute , :training_task_status ]
before_filter :authorize , :only = > [ :show , :settings , :edit , :sort_project_members , :update , :modules , :close , :reopen , :view_homework_attaches , :course ]
before_filter :authorize_global , :only = > [ :new , :create , :view_homework_attaches ]
before_filter :require_admin , :only = > [ :copy , :unarchive , :calendar ]
before_filter :require_admin_or_manager , :only = > [ :destroy ]
before_filter :file
before_filter :local_exam
# 除非项目内人员,不可查看成员, TODO: 完了写报表里去
# before_filter :memberAccess, only: :member
# accept_rss_auth :index
accept_api_auth :index , :show , :create , :update , :destroy
after_filter :only = > [ :create , :edit , :update , :archive , :unarchive , :destroy ] do | controller |
if controller . request . post?
controller . send :expire_action , :controller = > 'welcome' , :action = > 'robots'
end
end
helper :bids
include BidsHelper
helper :contests
include ContestsHelper
helper :sort
include SortHelper
helper :custom_fields
include CustomFieldsHelper
helper :issues
helper :queries
include QueriesHelper
helper :repositories
include RepositoriesHelper
include ProjectsHelper
helper :members
helper :activities
helper :documents
helper :watchers
# helper :watcherlist
helper :words
helper :project_score
helper :user_score
include UsersHelper
### added by william
include ActsAsTaggableOn :: TagsHelper
include ApplicationHelper
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 )
# 仅仅为了转换Gitlab地址
def project_home
rep = params [ :rep ]
login = params [ :username ]
begin
user = User . find_by_login ( login )
project = Project . find_by_sql ( " SELECT projects.* FROM `repositories`,`projects` where repositories.project_id = projects.id and projects.user_id = #{ user . try ( :id ) } and repositories.identifier=' #{ rep } ' " ) . first
respond_to do | format |
format . html { redirect_to ( :controller = > 'repositories' , :action = > 'show' , :id = > project . id , :repository_id = > rep ) }
end
rescue
render_404
return
end
end
#查找组织
def search_public_orgs_not_in_project
condition = '%%'
if ! params [ :name ] . nil?
condition = " % #{ params [ :name ] . strip } % " . gsub ( " " , " " )
end
limit = 15
project_org_ids = OrgProject . find_by_sql ( " select distinct organization_id from org_projects where project_id = #{ params [ :id ] } " ) . map ( & :organization_id ) << 0
@orgs_not_in_project = User . current . organizations . where ( " organizations.id not in ( #{ project_org_ids . join ( ',' ) } ) and organizations.name like ? " , condition ) . page ( params [ :page ] . to_i || 1 ) . per ( limit )
@org_count = User . current . organizations . where ( " organizations.id not in ( #{ project_org_ids . join ( ',' ) } ) and organizations.name like ' #{ condition } ' " ) . count
# if project_org_ids.empty?
# @orgs_not_in_project = Organization.where("(is_public or creator_id =?) = 1 and name like ?",User.current.id, condition).page((params[:page].to_i || 1)).per(limit)
# @org_count = Organization.where("is_public = 1 or creator_id =?", User.current.id).where("name like ?", condition).count
# else
# project_org_ids = "(" + project_org_ids.join(',') + ")"
# @orgs_not_in_project = Organization.where("id not in #{project_org_ids} and (is_public = 1 or creator_id =?) and name like ?", User.current.id, condition).page((params[:page].to_i || 1)).per(limit)
# @org_count = Organization.where("id not in #{project_org_ids} and (is_public = 1 or creator_id =?)", User.current.id).where("name like ?", condition).count
# end
@orgs_page = Paginator . new @org_count , limit , params [ :page ]
@no_roll_hint = params [ :hint_flag ]
#render :json => {:orgs => @orgs_not_in_project, :count => @org_count}.to_json
respond_to do | format |
format . js
end
end
def index
render_404
end
def courserender_404
end
# Time 2015-01-29 11:19:11
# Author lizanle
# Description 项目搜索方法
def search
# 如果有名字,就按名字搜索,如果没有,就展示所有,用Karminari分页
if params [ :name ] . present?
@project_pages = Project . project_entities . visible . like ( params [ :name ] ) . page ( params [ :page ] ) . per ( 10 )
else
@project_pages = Project . project_entities . visible . page ( params [ :page ] ) . per ( 10 )
end
@projects = @project_pages . order ( " created_on desc " )
@limit = 10 #per_page_option
@project_count = Project . project_entities . visible . like ( params [ :name ] ) . page ( params [ :page ] ) . count
@project_pages = Paginator . new @project_count , @limit , params [ 'page' ]
@name = params [ :name ]
@type = 'projects'
respond_to do | format |
format . html {
render :layout = > 'base'
scope = Project
unless params [ :closed ]
scope = scope . active
end
}
# 需要到处atom使用的格式 ( redmine自带)
format . atom {
projects = Project . visible . order ( 'created_on DESC' ) . limit ( Setting . feeds_limit . to_i ) . all
render_feed ( projects , :title = > " #{ Setting . app_title } : #{ l ( :label_project_latest ) } " )
}
end
end
# Time 2015-01-29 16:13:20
# Author lizanle
# Description 项目首页中用户反馈 方法
def feedback
@page = params [ :page ] . to_i
# Find the page of the requested reply
@jours = @project . journals_for_messages . where ( 'm_parent_id IS NULL' ) . order ( 'created_on DESC' )
limit = 10
offset = @jours . count ( :conditions = > [ " #{ JournalsForMessage . table_name } .id > ? " , params [ :r ] . to_i ] )
page = 1 + offset / limit
if params [ :r ] && @page . nil?
@page = @page < 0 ? 1 : @page
end
@page = @page > page ? page : @page
@jour = paginateHelper @jours , 10
@state = false
respond_to do | format |
format . html
format . api
end
end
def project_respond
project_id = request . headers [ " Referer " ] . match ( ( %r|/([0-9]{1,})/| ) ) [ 1 ]
parent_id = params [ :reference_id ]
author_id = User . current . id
reply_user_id = params [ :reference_user_id ]
reply_id = params [ :reference_message_id ]
content = params [ :project_respond ]
options = { :user_id = > author_id ,
:m_parent_id = > parent_id ,
:m_reply_id = > reply_id ,
:reply_id = > reply_user_id ,
:notes = > content ,
:is_readed = > false }
@jfm = Project . add_new_jour ( nil , nil , project_id , options )
@save_succ = @jfm . errors . empty?
respond_to do | format |
format . js
end
end
def new
if User . current . login? && User . current . mail . present?
@issue_custom_fields = IssueCustomField . sorted . all
@trackers = Tracker . sorted . all
@project = Project . new
@project . safe_attributes = params [ :project ]
if params [ :course_id ]
@course = Course . find params [ :course_id ]
elsif params [ :contest_id ]
@contest = Contest . find params [ :contest_id ]
end
render :layout = > 'base_edu'
elsif User . current . mail . blank?
redirect_to my_account_path
else
redirect_to signin_url
end
end
def share
@shares = @project . shares . reverse
@base_courses_tag = @project . project_type
respond_to do | format |
format . html { render :layout = > 'base_courses' if @base_courses_tag == 1 }
format . api
end
end
# 注意: 修改该方法的时候注意同步修改forked方法
# forked方法也会创建项目
def create
unless User . current . login?
redirect_to signin_url
return
end
ActiveRecord :: Base . transaction do
begin
# 创建项目
@project = Project . new
@project . safe_attributes = params [ :project ]
@project . user_id = User . current . id
params [ :project ] [ :is_public ] ? @project . is_public = 1 : @project . is_public = 0
if @project . save!
r = Role . givable . find_by_id ( Setting . new_project_user_role_id . to_i ) || Role . givable . first
m = Member . new ( :user = > User . current , :roles = > [ r ] )
# project's score
if ProjectScore . where ( " project_id=? " , @project . id ) . first . nil?
ProjectScore . create ( :project_id = > @project . id , :score = > 0 )
end
# end
project_info = ProjectInfo . new ( :user_id = > User . current . id , :project_id = > @project . id )
@project . members << m
@project . project_infos << project_info
identifier = generate_identifier
logger . info ( " project rep_identifier is #{ identifier } " )
repository = Repository . new
repository . type = 'Repository::Gitlab'
repository . identifier = identifier
repository . url = identifier
repository . project_id = @project . id
repository . save!
s = Trustie :: Gitlab :: Sync . new
gproject = s . create_project ( @project , repository )
raise " 版本库创建失败 " if gproject . try ( :id ) . blank?
@project . update_column ( :rep_identifier , identifier )
flash [ :notice ] = l ( :notice_successful_create )
redirect_to settings_project_url ( @project )
end
rescue Exception = > e
logger . error ( " failed: create repository #{ e . message } " )
flash [ :notice ] = " 项目创建失败,请稍后重试 "
redirect_to new_project_path
raise ActiveRecord :: Rollback
end
end
end
# 随机生成唯一标识
def generate_identifier
code = " p " + DCODES . sample ( 8 ) . join
return generate_identifier if Project . where ( rep_identifier : code ) . present?
code
end
def copy
@issue_custom_fields = IssueCustomField . sorted . all
@trackers = Tracker . sorted . all
@source_project = Project . find ( params [ :id ] )
if request . get?
@project = Project . copy_from ( @source_project )
@project . identifier = Project . next_identifier if Setting . sequential_project_identifiers?
else
Mailer . with_deliveries ( params [ :notifications ] == '1' ) do
@project = Project . new
@project . safe_attributes = params [ :project ]
if validate_parent_id && @project . copy ( @source_project , :only = > params [ :only ] )
@project . set_allowed_parent! ( params [ :project ] [ 'parent_id' ] ) if params [ :project ] . has_key? ( 'parent_id' )
flash [ :notice ] = l ( :notice_successful_create )
redirect_to settings_project_url ( @project )
elsif ! @project . new_record?
# Project was created
# But some objects were not copied due to validation failures
# (eg. issues from disabled trackers)
# TODO: inform about that
redirect_to settings_project_url ( @project )
end
end
end
rescue ActiveRecord :: RecordNotFound
# source_project not found
render_404
end
# Time 2015-01-29 10:42:00
# Author lizanle
# Description 项目动态展示方法,删除了不必要的代码
def show
# 顶部导航
@project_menu_type = 1
# 更新消息为已读
update_message_status ( User . current , @project )
# over
if params [ :jump ] && redirect_to_project_menu_item ( @project , params [ :jump ] )
return
end
@author = params [ :user_id ] . blank? ? nil : User . active . find ( params [ :user_id ] )
@page = params [ :page ] ? params [ :page ] . to_i + 1 : 0
# 根据私密性,取出符合条件的所有数据
if User . current . member_of? ( @project ) || User . current . admin?
case params [ :type ]
when nil
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type in ('Issue', 'TrainingTask','Message','News', 'Project', 'Attachment','Commit','AppliedProject') " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
when 'issue'
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type = 'Issue' " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
when 'training_task'
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type = 'TrainingTask' " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
when 'news'
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type = 'News' " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
when 'message'
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type = 'Message' " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
when 'attachment'
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type = 'Attachment' " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
when 'applied_project'
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type = 'AppliedProject' " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
end
else
@events_pages = ForgeActivity . includes ( :project ) . where ( " forge_activities.project_id = ? and projects.is_public = ? and forge_act_type != ? " , @project , 1 , " Document " ) . order ( " created_at desc " ) . page ( params [ 'page' || 1 ] ) . per ( 10 ) ;
end
@type = params [ :type ]
# 版本库统计图
# unless @project.gpid.nil? || @project.project_score.changeset_num == 0
# # rep_statics_commit = @project.rep_statics.order("commits_num desc")
# rep_statics_commit = RepStatics.find_by_sql("SELECT * FROM `rep_statics` where project_id = #{@project.id} order by commits_num desc limit 10")
# rep_statics_code = RepStatics.find_by_sql("SELECT * FROM `rep_statics` where project_id = #{@project.id} order by changeset desc limit 10")
# # rep_statics_code = @project.rep_statics.sort_by {|u| u.changeset}.reverse
# @a_uname = rep_statics_commit.map {|s| s.uname }
# @a_uname_code = rep_statics_code.map {|s| s.uname }
# @a_commits_num = rep_statics_commit.map {|s| s.commits_num.to_i }
# @a_commits_add = rep_statics_code.map {|s| s.add.to_i }
# @a_commits_del = rep_statics_code.map {|s| s.del.to_i }
# @a_commits_changeset = rep_statics_code.map {|s| s.changeset.to_i }
# g = Gitlab.client
# begin
# gid = @project.gpid
# g_project = g.project(gid)
# g_branch = g_project.default_branch.to_s
# rescue =>e
# logger.error("get default branch failed: " + e)
# end
# @rev = g_branch.nil? ? "master" : g_branch
# end
# 根据对应的请求,返回对应的数据
respond_to do | format |
format . html
format . api
format . js
end
end
def settings
# 顶部导航
@project_menu_type = 10
if @project . is_child_training_project?
return render_404
end
# 修改查看消息状态
applied_messages = ForgeMessage . where ( " user_id =? and project_id =? and forge_message_type =? and viewed =? " , User . current . id , @project , " AppliedProject " , 0 )
applied_messages . update_all ( :viewed = > true )
@issue_custom_fields = IssueCustomField . sorted . all
@issue_category || = IssueCategory . new
@member || = @project . members . new
@trackers = Tracker . sorted . all
@wiki || = @project . wiki
@select_tab = params [ :tab ]
#找出所有不属于项目的公共组织
project_org_ids = OrgProject . find_by_sql ( " select distinct organization_id from org_projects where project_id = #{ @project . id } " )
if project_org_ids . empty?
@orgs_not_in_project = Organization . where ( " is_public = 1 " )
else
project_org_ids = " ( " + project_org_ids . join ( ',' ) + " ) "
@orgs_not_in_project = Organization . where ( " id not in #{ project_org_ids } and is_public = 1 " )
end
# 里程碑
@versions = @project . shared_versions . sort
# 处理从新建版本库返回来的错误信息
if ! params [ :repository_error_message ] . to_s . blank?
html = " "
errors = params [ :repository_error_message ] . flatten
errors . each do | error |
# 版本库路径为空的错误信息不予提示
if ( error! = l ( :label_repository_path_not_null ) )
html << error << " ; "
end
end
if params [ :repository ] == " pswd_is_null "
html << l ( :label_password_not_null )
end
flash . now [ :error ] = html if ! html . to_s . blank?
end
# # for: 设置默认分支
# @gitlab_repository = Repository.where(:project_id => @project, :type => "Repository::Gitlab").first
# unless @gitlab_repository.nil?
# gitlab_address = Redmine::Configuration['gitlab_address']
# creator = @project.owner.try(:login)
# @repos_url = gitlab_address+"/" + creator + "/" + @gitlab_repository.identifier+"."+"git"
# end
#
# scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
# @repository = Repository.factory(scm)
# @repository.is_default = @project.repository.nil?
# @repository.project = @project
# @gitlab_rep = Repository.where(:type => "Repository::Gitlab", :project_id => @project).first
# unless @project.gpid.nil?
# g = Gitlab.client
# @gitlab_branches = g.branches(@project.gpid)
# @branch_names = @gitlab_branches.map{|b| b.name}
# @gitlab_default_branch = g.project(@project.gpid).default_branch
# end
end
# 项目邀请用户加入实现过程
# 两种情况: 1、系统外用户; 2、系统内用户 (通过邮件判定)
def send_mail_to_member
# 该邮箱未注册过
if ! params [ :mail ] . blank? && User . find_by_mail ( params [ :mail ] . to_s ) . nil?
if ! User . where ( " login =? " , params [ :mail ] ) . first . nil?
# 用户名唯一,用户修改邮箱,未修改用户名,用户名等同邮箱的情况,默认改用户已经注册
user = User . find_by_login ( params [ :mail ] . to_s )
if ! user . member_of? ( @project )
# 如果已经邀请过该用户,则不重复发送
if InviteList . where ( " project_id =? and mail =? " , @project . id , params [ :mail ] . to_s ) . first . nil?
email = params [ :mail ]
# Mailer.request_member_to_project(email, @project, User.current).deliver
flash [ :notice ] = l ( :notice_email_sent , :value = > email )
else
flash [ :error ] = l ( :notice_email_invited )
end
else
flash [ :error ] = l ( :label_member_of_project , :value = > email )
end
else
email = params [ :mail ]
first_name = params [ :first_name ]
last_name = params [ :last_name ]
gender = params [ :gender ]
# Mailer.send_invite_in_project(email, @project, User.current, first_name, last_name, gender).deliver
@is_zhuce = false
flash [ :notice ] = l ( :notice_email_sent , :value = > email )
end
# 邮箱地址已被注册
elsif ! User . find_by_mail ( params [ :mail ] . to_s ) . nil?
user = User . find_by_mail ( params [ :mail ] . to_s )
if ! user . member_of? ( @project )
# 如果已经邀请过该用户,则不重复发送
invite_list = InviteList . where ( " project_id =? and mail =? " , @project . id , params [ :mail ] . to_s ) . first
if invite_list . nil?
email = params [ :mail ]
# Mailer.request_member_to_project(email, @project, User.current).deliver
flash [ :notice ] = l ( :notice_email_sent , :value = > email )
else
# 已经发送过了, 则隔3小时才能再次发送
if Time . now - invite_list . created_at > 10800
email = params [ :mail ]
# Mailer.request_member_to_project(email, @project, User.current).deliver
flash [ :notice ] = l ( :notice_email_sent , :value = > email )
else
flash [ :error ] = l ( :notice_email_invited )
end
end
else
flash [ :error ] = l ( :label_member_of_project , :value = > email )
end
else
@is_zhuce = true
end
respond_to do | format |
format . html { redirect_to invite_members_by_mail_project_url ( @project ) }
end
end
# 发送邮件邀请新用户页面对应方法
def invite_members_by_mail
if User . current . member_of? ( @project ) || User . current . admin?
@inviter_lists = InviteList . where ( project_id : @project . id ) . order ( " created_at desc " )
# @inviters = []
# @waiters = []
# unless @inviter_lists.blank?
# @inviter_lists.each do|inviter_list|
# unless inviter_list.user.nil?
# if inviter_list.user.member_of?(@project)
# @inviters << inviter_list.user
# @inviters_count = @inviters.size
# else
# @waiters << inviter_list.user
# @waiters_count = @waiters.size
# end
# end
# end
# end
@is_zhuce = false
respond_to do | format |
format . html
format . js
end
else
render_403
end
end
# 邀请Trustie注册用户
# def invite_members
# if User.current.member_of?(@project) || User.current.admin?
# @member ||= @project.members.new
# respond_to do |format|
# format.html
# end
# else
# render_403
# end
# end
def edit
end
def set_public_or_private
@project = Project . find ( params [ :id ] )
if @project . is_public?
@project . update_attribute ( :is_public , 0 )
else
@project . update_attribute ( :is_public , 1 )
end
end
def project_watcherlist
unless @project . nil?
if ! @project . is_public? && ! User . current . member_of? ( @project ) && ! User . current . admin?
render_403
else
@users -= watched . watcher_users if @watched
end
@watchers = @project . watcher_users
@limit = 32
@is_remote = true
@watchers_count = @watchers . count
@watcher_pages = Paginator . new @watchers_count , @limit , params [ 'page' ] || 1
@offset || = @watcher_pages . offset
@watchers = paginateHelper @watchers , @limit
end
end
# include CoursesHelper
def member
# 消息"同意加入项目"
@project_menu_type = 8
# if params[:message_id]
# message_invite(params[:message_id], params[:key])
# end
# update_messsages_to_viewed("ForgeMessage", @project)
# params[:login]为邮箱邀请用户加入,主要功能:
# 1、自动注册
# 2、加入项目、创建角色
# 3、用户得分
# if params[:mail]
# userid = Token.find_by_value(params[:token]).user_id
# user = User.find(userid)
# user.activate!
# Member.create(:role_ids => [4], :user_id => userid, :project_id => params[:id])
# UserGrade.create(:user_id => userid, :project_id => params[:id])
# token = Token.get_token_from_user(user, 'autologin')
# #user = User.try_to_autologin(token.value)
# if user
# start_user_session(user)
# user.save
# redirect_to project_member_path(params[:id])
# return
# # account_ project_member_path(params[:id])
# flash[:notice] = l(:label_mail_invite_success)
# end
# end
# 私有项目非项目成员无法访问成员列表
unless @project . is_public?
return render_403 unless ( User . current . member_of? ( @project ) || User . current . admin? )
end
## 有角色参数的才是课程,没有的就是项目
@render_file = 'project_member_list'
# 判断是否课程
= begin
if @project . project_type == Project :: ProjectType_course
@teachers = searchTeacherAndAssistant ( @project )
@canShowCode = isCourseTeacher ( User . current . id )
case params [ :role ]
when '1'
@subPage_title = l :label_teacher_list
@members = searchTeacherAndAssistant ( @project )
when '2'
@subPage_title = l :label_student_list
@members = searchStudent ( @project )
else
@subPage_title = ''
@members = @project . member_principals . includes ( :roles , :principal ) . all . sort
end
else
if ! @project . is_public? && ! User . current . member_of? ( @project ) && ! User . current . admin?
render_403
else
roles = Role . find_all_givable
@subPage_title = l :label_member_list
@members = @project . member_principals . includes ( :roles , :principal ) . joins ( " LEFT JOIN #{ OptionNumber . table_name } ON #{ OptionNumber . table_name } .user_id = #{ Member . table_name } .user_id and #{ OptionNumber . table_name } .score_type = 2 AND #{ Member . table_name } .project_id = #{ OptionNumber . table_name } .project_id " ) . order ( " #{ OptionNumber . table_name } .total_score DESC " ) . all
@applied_members = appied_project_members ( @project , @members )
end
end
= end
@members = @project . member_principals . reorder ( " members.id asc " ) . includes ( :roles , :principal ) . all
@members = paginateHelper @members , 20
end
# 搜索非项目成员的用户
def search_none_user
if params [ :search ] && params [ :search ] . lstrip . rstrip != " "
scope = Principal . active . sorted . not_member_of ( @project ) . where ( " mail is not null and mail != '' " ) . like ( params [ :search ] )
else
scope = Principal . active . sorted . not_member_of ( @project ) . where ( " mail is not null and mail != '' " )
end
@members = paginateHelper scope , 5
end
def member_forked
@forked_projects = Project . where ( :forked_from_project_id = > @project . id )
@limit = 32
@is_remote = true
@forked_count = @forked_projects . count
@forked_pages = Paginator . new @forked_count , @limit , params [ 'page' ] || 1
@offset || = @forked_pages . offset
@forked_projects = paginateHelper @forked_projects , @limit
# @forked_members = User.find_by_sql("SELECT u.* FROM `projects` p,`users` u where p.user_id = u.id and p.forked_from_project_id = #{@project.id} ;")
end
def update_message_status ( user , project )
# 更新加入项目消息
project__messages = ForgeMessage . where ( " forge_message_type in ('ProjectInvite', 'JoinProject', 'RemoveFromProject') and user_id =? and project_id =? " , user , project )
project__messages . update_all ( :viewed = > true ) unless project__messages . blank?
end
def message_invite ( message_id , key )
forge_message = ForgeMessage . find ( message_id )
if key == forge_message . secret_key
# 情况:用户收到邀请邮件还没看,但是管理员已经把该用户添加进项目
if Member . where ( " user_id =? and project_id =? " , forge_message . user_id , forge_message . project_id ) . first . nil?
Member . create ( :role_ids = > [ 4 ] , :user_id = > forge_message . user_id , :project_id = > forge_message . project_id )
UserGrade . create ( :user_id = > forge_message . user_id , :project_id = > forge_message . project_id )
end
end
end
#判断指定用户是否为课程教师
def isCourseTeacher ( id )
result = false
if @teachers . find_by_user_id ( id ) != nil
result = true
end
result
end
def sort_project_members project , members
#userGrade = UserGrade.where(:project_id => project.id)
users = UserGrade . where ( :project_id = > project . id ) .
order ( 'grade DESC' ) .
joins ( " LEFT JOIN users ON users.id = user_grades.id " ) .
select ( " DISTINCT user_grades.user_id " )
memberlist = [ ]
users . each do | user |
members . each do | member |
if member [ :user_id ] == user [ :user_id ]
memberlist << member
end
end
end
memberlist
end
def appied_project_members ( project , members )
users = AppliedProject . where ( :project_id = > project . id )
memberlist = [ ]
users . each do | user |
members . each do | member |
if member [ :user_id ] == user [ :user_id ]
memberlist << member
end
end
end
memberlist
end
def file
end
def local_exam
if LocalSetting . first . try ( :exam ) && ! User . current . admin?
render_403
end
end
def statistics
end
#end
# 获取项目tree目录的最新提交记录
# 异步请求
# gpid, rev, ent_name, g
def repository_tree_changes
rev = params [ :rev ]
ent_path = params [ :ent_path ]
gpid = params [ :gpid ]
g = Gitlab . client
begin
result = g . rep_last_changes ( gpid , :rev = > rev , :path = > ent_path )
result = { :message = > result . message , :author_name = > User . find_by_mail ( result . author_email ) . nil? ? result . author_email : User . find_by_mail ( result . author_email ) . show_name , :time = > distance_of_time_in_words ( result . time , Time . now ) }
rescue Exception = > e
puts e
end
render :json = > result
end
def update
@project . safe_attributes = params [ :project ]
@project . organization_id = params [ :organization_id ]
params [ :project ] [ :is_public ] == " on " ? @project . is_public = 1 : @project . is_public = 0
params [ :project ] [ :hidden_repo ] == " on " ? @project . hidden_repo = 1 : @project . hidden_repo = 0
# # 更新公开私有时同步gitlab公开私有
# if !@project.gpid.nil? && @project.is_public != (params[:project][:is_public] == "on" ? 1 : 0)
# g = Gitlab.client
# params[:project][:is_public] == "on" ? g.edit_project(@project.gpid, 20, params[:branch]) : g.edit_project(@project.gpid, 0, params[:branch])
# end
# end
if validate_parent_id && @project . save
@project . set_allowed_parent! ( params [ :project ] [ 'parent_id' ] ) if params [ :project ] . has_key? ( 'parent_id' )
if params [ :project ] [ :is_public ] == '0'
project_status = ProjectStatus . find_by_project_id ( @project . id )
project_status . destroy if project_status
elsif params [ :project ] [ :is_public ] == '1'
project_status = ProjectStatus . create ( :project_id = > @project . id , :watchers_count = > @project . watchers . count , :changesets_count = > @project . changesets . count , :grade = > 0 , :project_type = > @project . project_type )
end
respond_to do | format |
format . html {
flash [ :notice ] = l ( :notice_successful_update )
redirect_to settings_project_url ( @project , :course = > @project . project_type )
}
format . api { render_api_ok }
end
else
respond_to do | format |
format . html {
settings
render :action = > 'settings'
}
format . api { render_validation_errors ( @project ) }
end
end
end
def add_script
if User . current . admin? || User . current . member_of? ( @project )
if @project . update_attribute ( :script , params [ :project_script ] )
@notice = " 脚本添加成功 "
else
@notice = " 脚本添加失败 "
end
else
return render_403
end
end
def modules
@project . enabled_module_names = params [ :enabled_module_names ]
flash [ :notice ] = l ( :notice_successful_update )
redirect_to settings_project_url ( @project , :tab = > 'modules' )
end
GITLABTYPE = " Repository::Gitlab "
def archive
if request . post?
if @project . destroy && @project . gpid
# 删除版本库信息
begin
g = Gitlab . client
g . delete_project ( @project . gpid )
rescue Exception = > e
puts e
end
# 删除Trustie版本库记录
repoisitory = Repository . where ( :project_id = > @project . id , :type = > GITLABTYPE ) . first
repoisitory . delete
@project . update_column ( :gpid , nil )
@project . update_column ( :forked_from_project_id , nil )
else
flash [ :error ] = l ( :error_can_not_archive_project )
end
unless @project . archive
end
end
if params [ :type ] == " project "
redirect_to user_path ( User . current )
else
redirect_to admin_projects_url ( :status = > params [ :status ] )
end
end
def unarchive
@project . unarchive if request . post? && ! @project . active?
redirect_to admin_projects_url ( :status = > params [ :status ] )
end
# 弹框提醒:
# 自己不能参加自己的实训项目
# 没有建立版本库的项目不能开启实训
# 已经实训过直接跳入
#
def training_chiled_project_exec
if ! User . current . logged?
return render_403
end
respond_to do | format |
format . js
end
end
# training_status: 默认为0; 1代表实训项目; 2: 代表实训子项目
def training_project_execute
if @project . training_tasks . count == 0
@notice = " 实训开启失败:请先发布实训任务 "
return
elsif Repository . where ( :project_id = > @project . id , :type = > " Repository::Gitlab " ) . count == 0
@notice = " 实训开启失败:请先创建版本库 "
return
end
jobName = " #{ @project . id } "
pipeLine = " #{ Base64 . encode64 ( @project . script ) } "
uri = URI ( " http://123.59.135.74:9999/jenkins-exec/api/createJob " )
params = { jobName : jobName , pipeLine : pipeLine }
res = uri_exec uri , params
training_project_notice res
if res [ 'code' ] == 0
@project . update_attribute ( :training_status , 1 )
end
end
def training_project_update
jobName = " #{ @project . id } "
pipeLine = " #{ Base64 . encode64 ( @project . script ) } "
uri = URI ( " http://123.59.135.74:9999/jenkins-exec/api/updateJob " )
params = { jobName : jobName , pipeLine : pipeLine }
res = uri_exec uri , params
training_project_notice res
if res [ 'code' ] == 0
@project . update_attribute ( :training_status , 1 )
end
end
def training_project_notice res
if res [ 'code' ] == 0
@notice = " 实训开启成功 "
elsif res [ 'code' ] == - 2
@notice = " Job已存在 "
else
@notice = res [ 'msg' ] . nil? ? " 实训开启失败 " : res [ 'msg' ]
end
end
# TrainintTask.status 0: 评测中 1: 评测成功 2: 评测进行中
# 非项目成员、非实训子项目不允许执行该方法
def task_execute
if ! @project . is_child_training_project? || ! User . current . member_of? ( @project )
return render_403
end
taskId = params [ :training_task_id ]
jobName = @project . forked_from_project_id
@training_task = TrainingTask . find ( taskId )
step = @training_task . position
rep_identify = Repository . where ( :project_id = > @project . id , :type = > " Repository::Gitlab " ) . first . try ( :identifier )
gitlab_address = Redmine :: Configuration [ 'gitlab_address' ]
gitUrl = gitlab_address . to_s + " / " + @project . owner . to_s + " / " + rep_identify + " . " + " git "
gitUrl = Base64 . encode64 ( gitUrl )
if @training_task . status == 0
params = { :jobName = > " #{ jobName } " , :taskId = > " #{ taskId } " , :step = > " #{ step } " , :gitUrl = > " #{ gitUrl } " }
uri = URI . parse ( " http://123.59.135.74:9999/jenkins-exec/api/buildJob " )
begin
res = uri_exec uri , params
# 轮询获取
for i in 0 .. 60 do
sleep ( 1 )
result = TrainingTask . where ( :id = > @training_task . id ) . first . try ( :result )
if ( result != 0 )
break
end
end
# @training_task = TrainingTask.find(@training_task.id)
@page = params [ :page ] ? params [ :page ] . to_i + 1 : 0
@events_pages = ForgeActivity . where ( " project_id = ? and forge_act_type in ('Issue', 'TrainingTask','Message','News', 'Project', 'Attachment','Commit') " , @project ) . includes ( :forge_act ) . order ( " updated_at desc " ) . limit ( 10 ) . offset ( @page * 10 )
rescue Exception = > e
puts e
end
end
respond_to do | format |
format . js
end
end
# def uri_exec uri, params
# # res = Net::HTTP.post_form(uri, params).body
# # res = JSON.parse(res)
# end
# 开启实训项目,学生会fork一个项目并自动发送任务
def training_project_extend
@project = Project . find ( params [ :id ] )
@repository = Repository . where ( " project_id =? and type =? " , @project . id , " Repository::Gitlab " )
# 如果当前用户已经fork过该项目, 不会新fork项目, 则跳至已fork的项
unless has_forked? ( @project , User . current )
project = project_from_current_project ( @project . id , User . current . id )
redirect_to project_path ( project )
else
ActiveRecord :: Base . transaction do
g = Gitlab . client
if User . current . gid . nil?
s = Trustie :: Gitlab :: Sync . new
s . sync_user ( User . current )
end
gproject = g . fork ( @project . gpid , User . current . gid )
if gproject
new_training_project = copy_project_and_module ( @project , gproject )
forked_count = @project . forked_count . to_i + 1
@project . update_attributes ( :forked_count = > forked_count )
# 发布实训任务,只发布实训任务的第一个
publish_training_tasks ( @project . id , new_training_project . id , 1 , @project . user_id )
end
end
end
end
# 需要传Task ID
# 判断任务是否完成
# 如果完成则发送下一个任务直到任务结束
# TrainingTask.status 1 成功,其它失败
def training_task_status
status = params [ :status ] . to_i
task_id = params [ :taskId ]
message = Base64 . decode64 ( params [ :msg ] ) unless params [ :msg ] . blank?
begin
@training_task = TrainingTask . find ( task_id )
# 如果已经执行成功过,则不重复执行
return if @training_task . status == 1
original_project_id = Project . find ( @training_task . project_id ) . try ( :forked_from_project_id )
original_project = Project . find ( original_project_id )
rescue
return
end
original_tasks_count = original_project . training_tasks . count
position = @training_task . try ( :position )
# 测试,默认成功
if status == 0
ActiveRecord :: Base . transaction do
if position < original_tasks_count
# 继续发布下一个任务
publish_training_tasks original_project_id , @training_task . project_id , position + 1 , original_project . user_id
end
@training_task . update_attribute ( :status , 1 )
@training_task . update_attribute ( :result , 1 )
# 创建一条回复提醒
content = ( position == original_tasks_count ) ? " 恭喜您,您已经完成了实训项目的所有任务 " : " 恭喜您,您已经完成了本任务,请继续下一任务 "
add_training_task_journal ( content , original_project . user_id )
end
else
content = " 很抱歉,您的任务未通过,请继续加油,错误信息如下: #{ message } "
add_training_task_journal ( content , original_project . user_id )
# 失败的时候可以继续提交
@training_task . update_attribute ( :status , 0 )
@training_task . update_attribute ( :result , 2 )
end
end
# 创建一条回复
def add_training_task_journal content , user_id
jour = Journal . new
jour . user_id = user_id
jour . notes = content
jour . journalized = @training_task
jour . save
update_user_activity ( @training_task . class , @training_task . id )
update_forge_activity ( @training_task . class , @training_task . id )
end
# 实训开启成功后,发布第一个任务
# REDO:失败后提醒用户,及相关处理
def publish_training_tasks original_project_id , new_training_project_id , position , user_id
original_task = TrainingTask . where ( :project_id = > original_project_id , :position = > position ) . first
training_task = TrainingTask . new
training_task . save_attachments ( params [ :attachments ] || ( params [ :training_task ] && params [ :training_task ] [ :uploads ] ) )
training_task . subject = original_task . subject
training_task . description = original_task . description
training_task . position = original_task . position
training_task . project_id = new_training_project_id
training_task . author_id = User . current . id
begin
training_task . save
rescue Exception = > e
puts e
end
end
# 复制项目
def copy_project_and_module tproject , gproject
project = Project . new
project . name = tproject . name
project . is_public = tproject . is_public
project . status = tproject . status
project . description = tproject . description
project . hidden_repo = tproject . hidden_repo
project . user_id = User . current . id
project . project_type = 0
project . project_new_type = tproject . project_new_type
project . gpid = gproject . id
project . forked_from_project_id = tproject . id
project . enabled_module_names = tproject . enabled_module_names
if project . save
project . update_attribute ( :training_status , 2 )
r = Role . givable . find_by_id ( Setting . new_project_user_role_id . to_i ) || Role . givable . first
m = Member . new ( :user = > User . current , :roles = > [ r ] )
if ProjectScore . where ( " project_id=? " , project . id ) . first . nil?
ProjectScore . create ( :project_id = > project . id , :score = > false )
end
project_info = ProjectInfo . new ( :user_id = > User . current . id , :project_id = > project . id )
user_grades = UserGrade . create ( :user_id = > User . current . id , :project_id = > project . id )
Rails . logger . debug " UserGrade created: #{ user_grades . to_json } "
project_status = ProjectStatus . create ( :project_id = > @project . id , :watchers_count = > 0 , :changesets_count = > 0 , :project_type = > @project . project_type , :grade = > 0 )
Rails . logger . debug " ProjectStatus created: #{ project_status . to_json } "
project . members << m
project . project_infos << project_info
copy_repository ( project , gproject )
return project
else
respond_to do | format |
format . html { render :action = > 'forked' , :layout = > 'base_projects' }
format . api { render_validation_errors ( @project ) }
end
end
end
# 判断用户是否已经fork过该项目
def has_forked? ( project , user )
projects = Project . where ( " user_id =? " , user )
projects . map ( & :forked_from_project_id ) . detect { | s | s == @project . id } . nil? ? true : false
end
def copy_repository ( project , gproject )
repository = Repository . factory ( 'Git' )
repository . project_id = project . id
repository . type = 'Repository::Gitlab'
repository . url = gproject . name
repository . identifier = gproject . name
repository = repository . save
end
# 资源库fork弹框
def forked_pop
respond_to do | format |
format . js
end
end
# 配置成员弹框
def delete_member_pop
@member = Member . find ( params [ :member ] . to_i )
respond_to do | format |
format . js
end
end
def close
@project . close
redirect_to project_url ( @project )
end
def reopen
@project . reopen
redirect_to project_url ( @project )
end
REP_TYPE = " Repository::Gitlab "
# Delete @project
def destroy
ActiveRecord :: Base . transaction do
g = Gitlab . client
g . delete_project ( @project . gpid )
# 删除Trustie版本库记录
repoisitory = Repository . where ( :project_id = > @project . id , :type = > GITLABTYPE ) . first
repoisitory . delete
@project . update_column ( :gpid , nil )
@project . update_column ( :forked_from_project_id , nil )
Tiding . where ( :container_id = > @project . id , :container_type = > [ " JoinProject " , " DealProject " , " ReporterJoinProject " , " ManagerJoinProject " ] ) . destroy_all
@project_to_destroy = @project
@project_to_destroy . destroy
end
respond_to do | format |
format . js
if params [ :type ] == " project "
format . html { redirect_to user_path ( User . current ) }
else
format . html { redirect_to admin_projects_url ( :status = > params [ :status ] ) }
end
end
# hide project in layout
@project = nil
end
# Delete @project's repository
def destroy_repository
if is_project_manager? ( User . current . id , @project . id )
@gitlab_repository = Repository . where ( :project_id = > @project , :type = > REP_TYPE ) . first
@is_true = params [ :is_true ]
unless @is_true . nil?
begin
g = Gitlab . client
d_project = g . delete_project ( @project . gpid )
if d_project
@gitlab_repository . destroy
@project . update_attribute ( :gpid , nil )
@gitlab_repository = nil
end
rescue Exception = > e
if @gitlab_repository
@gitlab_repository . destroy
@project . update_attribute ( :gpid , nil )
@gitlab_repository = nil
end
end
redirect_to new_project_repository_path ( @project )
end
else
return render_403
end
end
def show_projects_score
respond_to do | format |
format . html { render :layout = > " base_projects " }
format . js
end
end
def issue_score_index
respond_to do | format |
format . js
end
end
def news_score_index
end
def file_score_index
end
def code_submit_score_index
end
def projects_topic_score_index
end
# end
before_filter :toggleCourse , only : [ :finishcourse , :restartcourse ]
# 最好通过用户与项目的权限解决这种事情。还没写
def finishcourse
yesterday = Date . today . prev_day . to_time
@course_prefs . endup_time = yesterday
@save_flag = @course_prefs . save
respond_to do | format |
format . js
end
end
def restartcourse
day = Time . parse ( " 3000-01-01 " )
@course_prefs . endup_time = day
@save_flag = @course_prefs . save
respond_to do | format |
format . js {
render action : 'finishcourse'
}
end
end
def exit_project
@project = Project . find params [ :id ]
if User . current . login?
members = Member . where ( :user_id = > User . current . id , :project_id = > params [ :id ] ) . first
if User . current != @project . owner
members . destroy
# 移出的时候删除申请消息,不需要删除消息,所以不必要关联删除
applied_projects = AppliedProject . where ( :project_id = > @project . id , :user_id = > members . user_id ) . first
unless applied_projects . nil?
applied_projects . delete
end
end
respond_to do | format |
format . js
end
end
end
def store_mine
member = Member . where ( :project_id = > params [ :id ] , :user_id = > User . current . id ) . first
member . try ( :is_collect ) == 1 ? member . update_column ( :is_collect , 0 ) : member . update_column ( :is_collect , 1 )
end
# 项目收藏
def enshrine
@stores = Member . where ( :project_id = > params [ :id ] , :is_collect = > 1 ) . includes ( :user )
end
#加入私有项目
def join_project
respond_to do | format |
format . js
end
end
#朋友圈、科研组、开发组之间的切换
def change_project_type
@project . project_new_type = params [ :project_type ]
if @project . save
message = @project . project_new_type
else
message = " 0 "
end
render :json = > message
end
private
def memberAccess
# 如果是私有项目,项目成员不对外公开,公开项目成员列表对外公开。
unless @project . is_public?
render_403 unless User . current . member_of? ( @project )
end
end
def toggleCourse
@course_prefs = Course . find_by_extra ( @project . identifier )
unless ( @course_prefs . teacher == User . current || User . current . admin? )
render_403
end
end
def select_project_layout
project = Project . find_by_id ( params [ :id ] )
project || = @project || = @course || = params [ :course ] || = params [ :project_type ]
( project . try ( :project_type ) == Project :: ProjectType_project ) ? 'base_projects' : 'base_courses'
end
# Validates parent_id param according to user's permissions
# TODO: move it to Project model in a validation that depends on User.current
def validate_parent_id
return true if User . current . admin?
parent_id = params [ :project ] && params [ :project ] [ :parent_id ]
if parent_id || @project . new_record?
parent = parent_id . blank? ? nil : Project . find_by_id ( parent_id . to_i )
unless @project . allowed_parents . include? ( parent )
@project . errors . add :parent_id , :invalid
return false
end
end
true
end
#gcm
def desc_sort_course_by_avtivity ( activity_count , projects )
return projects if activity_count . size < 2
( activity_count . size - 2 ) . downto ( 0 ) do | i |
( 0 .. i ) . each do | j |
if activity_count [ j ] < activity_count [ j + 1 ]
projects [ j ] , projects [ j + 1 ] = projects [ j + 1 ] , projects [ j ]
activity_count [ j ] , activity_count [ j + 1 ] = activity_count [ j + 1 ] , activity_count [ j ]
end
end
end
return projects
end
def require_admin_or_manager
return unless require_login
if ! ( User . current . admin? || User . current . manager_of_project? ( @project . id ) )
render_403
return false
end
true
end
end