socialforge/app/controllers/projects_controller.rb

1330 lines
49 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
# 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 :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
# 除非项目内人员,不可查看成员, 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
# 仅仅为了转换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?
@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 => 'new_base'
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
@issue_custom_fields = IssueCustomField.sorted.all
@trackers = Tracker.sorted.all
@project = Project.new
@project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id]
@project.user_id = User.current.id
@project.project_new_type = params[:project_new_type]
params[:project][:is_public] ? @project.is_public = 1 : @project.is_public = 0
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
#unless User.current.admin?
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 => false)
end
# 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}"
#if params[:project][:is_public] == '1'
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}"
#end
@project.members << m
@project.project_infos << project_info
p = Project.find("#{@project.id}")
ps = ProjectsService.new
ps.send_wechat_create_project_notice User.current,p
#end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
attrs = {:parent_id => @project.parent_id}.reject {|k,v| v.nil?}
redirect_to new_project_url(attrs, :course => '0')
else
redirect_to settings_project_url(@project)
end
}
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
format.js
end
else
respond_to do |format|
format.html { render :action => 'new', :layout => 'new_base'}#Added by young
format.api { render_validation_errors(@project) }
end
end
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')", @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)
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
# 消息"同意加入项目"
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)
end
## 有角色参数的才是课程,没有的就是项目
@render_file = 'project_member_list'
# 判断是否课程
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
@members = paginateHelper @members, 32
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 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)
@project_to_destroy = @project
@project_to_destroy.destroy
end
respond_to do |format|
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
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