diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8cf3a2c35..9d54772f8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -245,6 +245,24 @@ class ApplicationController < ActionController::Base end end + def authorize_course(ctrl = params[:controller], action = params[:action], global = false) + allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @course || @course, :global => global) + if allowed + true + else + if @course && @course.archived? + render_403 :message => :notice_not_authorized_archived_project + else + deny_access + end + end + end + + def authorize_course_global(ctrl = params[:controller], action = params[:action], global = true) + authorize_course(ctrl, action, global) + end + + # Authorize the user for the requested action outside a project def authorize_global(ctrl = params[:controller], action = params[:action], global = true) authorize(ctrl, action, global) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 335426bf7..97b51416a 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -7,8 +7,8 @@ class CoursesController < ApplicationController menu_item l(:label_sort_by_influence), :only => :index before_filter :find_course, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches] - before_filter :authorize, :only => [:show, :settings, :edit, :update, :modules, :close, :reopen, :view_homework_attaches, :course] - before_filter :authorize_global, :only => [:view_homework_attaches, :new,:create] + before_filter :authorize_course, :only => [:show, :settings, :edit, :update, :modules, :close, :reopen, :view_homework_attaches, :course] + before_filter :authorize_course_global, :only => [:view_homework_attaches, :new,:create] before_filter :require_admin, :only => [:copy, :archive, :unarchive, :destroy, :calendar] before_filter :toggleCourse, only: [:finishcourse, :restartcourse] diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index 8f3e4eb79..bdc5afbfe 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -50,6 +50,21 @@ module CoursesHelper garble count end + def eventToLanguageCourse event_type, course + case event_type + when "issue-note" + l :label_issue + when "issue" + l :label_issue + when "attachment" + l :label_attachment + when "news" + l :label_notification + else + "" + end + end + def garble count count = count.round( 1-count.to_s.size ).to_i return count.to_s if count.to_s.size.eql?(1) diff --git a/app/models/board.rb b/app/models/board.rb index cb81e0a5a..b51790e19 100644 --- a/app/models/board.rb +++ b/app/models/board.rb @@ -18,6 +18,7 @@ class Board < ActiveRecord::Base include Redmine::SafeAttributes belongs_to :project + belongs_to :course has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC" has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC" belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id diff --git a/app/models/course.rb b/app/models/course.rb index 6200c1942..630bf67ac 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -22,6 +22,7 @@ class Course < ActiveRecord::Base has_many :homework_for_courses, :dependent => :destroy has_many :student, :through => :students_for_courses, :source => :user has_many :course_infos, :class_name => 'CourseInfos',:dependent => :destroy + has_many :enabled_modules, :dependent => :delete_all acts_as_taggable #acts_as_nested_set :order => 'name', :dependent => :destroy @@ -72,11 +73,44 @@ class Course < ActiveRecord::Base self.status == STATUS_ARCHIVED end - def self.visible_condition(user, options={}) + def self.visible_condition(user, options={}) allowed_to_condition(user, :view_course, options) end - # 返回用户组可以访问的课程 + def active? + self.status == STATUS_ACTIVE + end + + #课程权限判断 + def allows_to?(action) + if archived? + # No action allowed on archived projects + return false + end + unless active? || Redmine::AccessControl.read_action?(action) + # No write action allowed on closed projects + return false + end + # No action allowed on disabled modules + if action.is_a? Hash + allowed_actions.include? "#{action[:controller]}/#{action[:action]}" + else + allowed_permissions.include? action + end + end + + def allowed_permissions + @allowed_permissions ||= begin + module_names = enabled_modules.all(:select => :name).collect {|m| m.name} + Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name} + end + end + + def allowed_actions + @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten + end + + # 返回用户组可以访问的课程 def users_by_role members.includes(:user, :roles).all.inject({}) do |h, m| m.roles.each do |r| diff --git a/app/models/message.rb b/app/models/message.rb index 2421a7d4f..397e7283d 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -31,6 +31,10 @@ class Message < ActiveRecord::Base :include => {:board => :project}, :project_key => "#{Board.table_name}.project_id", :date_column => "#{table_name}.created_on" + acts_as_searchable :columns => ['subject', 'content'], + :include => {:board => :course}, + :course_key => "#{Board.table_name}.course_id", + :date_column => "#{table_name}.created_at" acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, :description => :content, :datetime => :updated_on, @@ -42,6 +46,8 @@ class Message < ActiveRecord::Base acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]}, :author_key => :author_id + acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]}, + :author_key => :author_id acts_as_watchable validates_presence_of :board, :subject, :content @@ -60,6 +66,7 @@ class Message < ActiveRecord::Base includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args)) } + safe_attributes 'subject', 'content' safe_attributes 'locked', 'sticky', 'board_id', :if => lambda {|message, user| @@ -67,7 +74,11 @@ class Message < ActiveRecord::Base } def visible?(user=User.current) - !user.nil? && user.allowed_to?(:view_messages, project) + if project + !user.nil? && user.allowed_to?(:view_messages, project) + elsif course + !user.nil? && user.allowed_to?(:view_messages, course) + end end def cannot_reply_to_locked_topic @@ -87,7 +98,7 @@ class Message < ActiveRecord::Base if parent && parent.id Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id}) end - board.reset_counters! + board.reset_counters!(board.id) end def sticky=(arg) @@ -102,6 +113,10 @@ class Message < ActiveRecord::Base board.project end + def course + board.course + end + def editable_by?(usr) usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))) end diff --git a/app/models/role.rb b/app/models/role.rb index 2902325d3..cba219d0d 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -151,7 +151,7 @@ class Role < ActiveRecord::Base if action.is_a? Hash allowed_actions.include? "#{action[:controller]}/#{action[:action]}" else - allowed_permissions.include? action + allowed_permissions.include? action end end diff --git a/app/models/user.rb b/app/models/user.rb index d664a0881..818b919ce 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -655,6 +655,27 @@ class User < Principal roles end + # 用户课程权限判断 + def roles_for_course(course) + roles = [] + # No role on archived courses + return roles if course.nil? || course.archived? + if logged? + # Find course membership + membership = membership(course) + if membership + roles = membership.roles + else + @role_non_member ||= Role.non_member + roles << @role_non_member + end + else + @role_anonymous ||= Role.anonymous + roles << @role_anonymous + end + roles + end + # Return true if the user is a member of project def member_of?(project) projects.to_a.include?(project) @@ -733,7 +754,20 @@ class User < Principal role.allowed_to?(action) && (block_given? ? yield(role, self) : true) } - elsif context && context.is_a?(Array) + #添加课程相关的权限判断 + elsif context && context.is_a?(Course) + return false unless context.allows_to?(action) + # Admin users are authorized for anything else + return true if admin? + + roles = roles_for_course(context) + return false unless roles + roles.any? {|role| + (context.is_public? || role.member?) && + role.allowed_to?(action) && + (block_given? ? yield(role, self) : true) + } + elsif context && context.is_a?(Array) if context.empty? false else diff --git a/app/views/courses/show.html.erb b/app/views/courses/show.html.erb index 8a6f51498..d41e3a80e 100644 --- a/app/views/courses/show.html.erb +++ b/app/views/courses/show.html.erb @@ -16,7 +16,7 @@
- <%= h(e.course) if @course.nil? || @course.id != e.course.id %> + <%= h(e.course) if @course.nil? || (e.course != nil && @course.id != e.course.id) %> <% if @canShowRealName %> <%= link_to_user(e.event_author) if e.respond_to?(:event_author) %>(<%= link_to_user(e.event_author,@canShowRealName) if e.respond_to?(:event_author) %>) diff --git a/app/views/users/_course_list_have_entity.html.erb b/app/views/users/_course_list_have_entity.html.erb index e29c87101..a0e721df5 100644 --- a/app/views/users/_course_list_have_entity.html.erb +++ b/app/views/users/_course_list_have_entity.html.erb @@ -1,6 +1,6 @@ |