Ability to close projects (read-only) (#3640).
A new permission (Close/reopen project) is available to give non-admin users the ability to close their projects. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@9883 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
1 parent
5961a1e70d
commit
ac56c0c99c
21 files changed
+213
-42
No files matched your search
@@ -19,7 +19,7 @@ class Principal < ActiveRecord::Base
|
||||
self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
|
||||
|
||||
has_many :members, :foreign_key => 'user_id', :dependent => :destroy
|
||||
has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
|
||||
has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}", :order => "#{Project.table_name}.name"
|
||||
has_many :projects, :through => :memberships
|
||||
has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
|
||||
|
||||
|
||||
+25
-10
@@ -20,6 +20,7 @@ class Project < ActiveRecord::Base
|
||||
|
||||
# Project statuses
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_CLOSED = 5
|
||||
STATUS_ARCHIVED = 9
|
||||
|
||||
# Maximum length for project identifiers
|
||||
@@ -161,12 +162,11 @@ class Project < ActiveRecord::Base
|
||||
# * :with_subprojects => limit the condition to project and its subprojects
|
||||
# * :member => limit the condition to the user projects
|
||||
def self.allowed_to_condition(user, permission, options={})
|
||||
base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
|
||||
if perm = Redmine::AccessControl.permission(permission)
|
||||
unless perm.project_module.nil?
|
||||
# If the permission belongs to a project module, make sure the module is enabled
|
||||
base_statement << " AND #{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.project_module}')"
|
||||
end
|
||||
perm = Redmine::AccessControl.permission(permission)
|
||||
base_statement = (perm && perm.read? ? "#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED}" : "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}")
|
||||
if perm && perm.project_module
|
||||
# If the permission belongs to a project module, make sure the module is enabled
|
||||
base_statement << " AND #{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.project_module}')"
|
||||
end
|
||||
if options[:project]
|
||||
project_statement = "#{Project.table_name}.id = #{options[:project].id}"
|
||||
@@ -325,6 +325,14 @@ class Project < ActiveRecord::Base
|
||||
update_attribute :status, STATUS_ACTIVE
|
||||
end
|
||||
|
||||
def close
|
||||
self_and_descendants.status(STATUS_ACTIVE).update_all :status => STATUS_CLOSED
|
||||
end
|
||||
|
||||
def reopen
|
||||
self_and_descendants.status(STATUS_CLOSED).update_all :status => STATUS_ACTIVE
|
||||
end
|
||||
|
||||
# Returns an array of projects the project can be moved to
|
||||
# by the current user
|
||||
def allowed_parents
|
||||
@@ -404,7 +412,7 @@ class Project < ActiveRecord::Base
|
||||
@rolled_up_trackers ||=
|
||||
Tracker.find(:all, :joins => :projects,
|
||||
:select => "DISTINCT #{Tracker.table_name}.*",
|
||||
:conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status = #{STATUS_ACTIVE}", lft, rgt],
|
||||
:conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> #{STATUS_ARCHIVED}", lft, rgt],
|
||||
:order => "#{Tracker.table_name}.position")
|
||||
end
|
||||
|
||||
@@ -423,20 +431,20 @@ class Project < ActiveRecord::Base
|
||||
def rolled_up_versions
|
||||
@rolled_up_versions ||=
|
||||
Version.scoped(:include => :project,
|
||||
:conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status = #{STATUS_ACTIVE}", lft, rgt])
|
||||
:conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> #{STATUS_ARCHIVED}", lft, rgt])
|
||||
end
|
||||
|
||||
# Returns a scope of the Versions used by the project
|
||||
def shared_versions
|
||||
if new_record?
|
||||
Version.scoped(:include => :project,
|
||||
:conditions => "#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND #{Version.table_name}.sharing = 'system'")
|
||||
:conditions => "#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED} AND #{Version.table_name}.sharing = 'system'")
|
||||
else
|
||||
@shared_versions ||= begin
|
||||
r = root? ? self : root
|
||||
Version.scoped(:include => :project,
|
||||
:conditions => "#{Project.table_name}.id = #{id}" +
|
||||
" OR (#{Project.table_name}.status = #{Project::STATUS_ACTIVE} AND (" +
|
||||
" OR (#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED} AND (" +
|
||||
" #{Version.table_name}.sharing = 'system'" +
|
||||
" OR (#{Project.table_name}.lft >= #{r.lft} AND #{Project.table_name}.rgt <= #{r.rgt} AND #{Version.table_name}.sharing = 'tree')" +
|
||||
" OR (#{Project.table_name}.lft < #{lft} AND #{Project.table_name}.rgt > #{rgt} AND #{Version.table_name}.sharing IN ('hierarchy', 'descendants'))" +
|
||||
@@ -515,6 +523,13 @@ class Project < ActiveRecord::Base
|
||||
s << ' root' if root?
|
||||
s << ' child' if child?
|
||||
s << (leaf? ? ' leaf' : ' parent')
|
||||
unless active?
|
||||
if archived?
|
||||
s << ' archived'
|
||||
else
|
||||
s << ' closed'
|
||||
end
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
|
||||
+4
-2
@@ -394,7 +394,7 @@ class User < Principal
|
||||
def roles_for_project(project)
|
||||
roles = []
|
||||
# No role on archived projects
|
||||
return roles unless project && project.active?
|
||||
return roles if project.nil? || project.archived?
|
||||
if logged?
|
||||
# Find project membership
|
||||
membership = memberships.detect {|m| m.project_id == project.id}
|
||||
@@ -456,9 +456,11 @@ class User < Principal
|
||||
def allowed_to?(action, context, options={}, &block)
|
||||
if context && context.is_a?(Project)
|
||||
# No action allowed on archived projects
|
||||
return false unless context.active?
|
||||
return false if context.archived?
|
||||
# No action allowed on disabled modules
|
||||
return false unless context.allows_to?(action)
|
||||
# No write action allowed on closed projects
|
||||
return false unless context.active? || Redmine::AccessControl.read_action?(action)
|
||||
# Admin users are authorized for anything else
|
||||
return true if admin?
|
||||
|
||||
|
||||
Reference in new issue
Block a user