summaryrefslogtreecommitdiffstats
path: root/app/controllers
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2006-12-05 20:45:04 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2006-12-05 20:45:04 +0000
commit96f83cc8f0f032554f771a59da22303cd473b878 (patch)
tree355a0d2ed653a5426c59ebf6a1fe65eba024b4d0 /app/controllers
parenteabc04d8368824965d3ac8de3fa84502e9c05d38 (diff)
downloadredmine-96f83cc8f0f032554f771a59da22303cd473b878.tar.gz
redmine-96f83cc8f0f032554f771a59da22303cd473b878.zip
trunk moved from /trunk/redmine to /trunk
git-svn-id: http://redmine.rubyforge.org/svn/trunk@67 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/account_controller.rb131
-rw-r--r--app/controllers/admin_controller.rb56
-rw-r--r--app/controllers/application.rb126
-rw-r--r--app/controllers/auth_sources_controller.rb83
-rw-r--r--app/controllers/custom_fields_controller.rb71
-rw-r--r--app/controllers/documents_controller.rb68
-rw-r--r--app/controllers/enumerations_controller.rb70
-rw-r--r--app/controllers/help_controller.rb47
-rw-r--r--app/controllers/issue_categories_controller.rb42
-rw-r--r--app/controllers/issue_statuses_controller.rb69
-rw-r--r--app/controllers/issues_controller.rb145
-rw-r--r--app/controllers/members_controller.rb41
-rw-r--r--app/controllers/my_controller.rb131
-rw-r--r--app/controllers/news_controller.rb42
-rw-r--r--app/controllers/projects_controller.rb469
-rw-r--r--app/controllers/reports_controller.rb164
-rw-r--r--app/controllers/roles_controller.rb84
-rw-r--r--app/controllers/trackers_controller.rb61
-rw-r--r--app/controllers/users_controller.rb92
-rw-r--r--app/controllers/versions_controller.rb57
-rw-r--r--app/controllers/welcome_controller.rb25
21 files changed, 2074 insertions, 0 deletions
diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb
new file mode 100644
index 000000000..ffd2419b3
--- /dev/null
+++ b/app/controllers/account_controller.rb
@@ -0,0 +1,131 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class AccountController < ApplicationController
+ layout 'base'
+ helper :custom_fields
+ include CustomFieldsHelper
+
+ # prevents login action to be filtered by check_if_login_required application scope filter
+ skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
+ before_filter :require_login, :except => [:show, :login, :lost_password, :register]
+
+ # Show user's account
+ def show
+ @user = User.find(params[:id])
+ @custom_values = @user.custom_values.find(:all, :include => :custom_field)
+ end
+
+ # Login request and validation
+ def login
+ if request.get?
+ # Logout user
+ self.logged_in_user = nil
+ else
+ # Authenticate user
+ user = User.try_to_login(params[:login], params[:password])
+ if user
+ self.logged_in_user = user
+ redirect_back_or_default :controller => 'my', :action => 'page'
+ else
+ flash.now[:notice] = l(:notice_account_invalid_creditentials)
+ end
+ end
+ end
+
+ # Log out current user and redirect to welcome page
+ def logout
+ self.logged_in_user = nil
+ redirect_to :controller => ''
+ end
+
+ # Enable user to choose a new password
+ def lost_password
+ if params[:token]
+ @token = Token.find_by_action_and_value("recovery", params[:token])
+ redirect_to :controller => '' and return unless @token and !@token.expired?
+ @user = @token.user
+ if request.post?
+ @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
+ if @user.save
+ @token.destroy
+ flash[:notice] = l(:notice_account_password_updated)
+ redirect_to :action => 'login'
+ return
+ end
+ end
+ render :template => "account/password_recovery"
+ return
+ else
+ if request.post?
+ user = User.find_by_mail(params[:mail])
+ # user not found in db
+ flash.now[:notice] = l(:notice_account_unknown_email) and return unless user
+ # user uses an external authentification
+ flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id
+ # create a new token for password recovery
+ token = Token.new(:user => user, :action => "recovery")
+ if token.save
+ # send token to user via email
+ Mailer.set_language_if_valid(user.language)
+ Mailer.deliver_lost_password(token)
+ flash[:notice] = l(:notice_account_lost_email_sent)
+ redirect_to :action => 'login'
+ return
+ end
+ end
+ end
+ end
+
+ # User self-registration
+ def register
+ redirect_to :controller => '' and return if $RDM_SELF_REGISTRATION == false
+ if params[:token]
+ token = Token.find_by_action_and_value("register", params[:token])
+ redirect_to :controller => '' and return unless token and !token.expired?
+ user = token.user
+ redirect_to :controller => '' and return unless user.status == User::STATUS_REGISTERED
+ user.status = User::STATUS_ACTIVE
+ if user.save
+ token.destroy
+ flash[:notice] = l(:notice_account_activated)
+ redirect_to :action => 'login'
+ return
+ end
+ else
+ if request.get?
+ @user = User.new(:language => $RDM_DEFAULT_LANG)
+ @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
+ else
+ @user = User.new(params[:user])
+ @user.admin = false
+ @user.login = params[:user][:login]
+ @user.status = User::STATUS_REGISTERED
+ @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
+ @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
+ @user.custom_values = @custom_values
+ token = Token.new(:user => @user, :action => "register")
+ if @user.save and token.save
+ Mailer.set_language_if_valid(@user.language)
+ Mailer.deliver_register(token)
+ flash[:notice] = l(:notice_account_register_done)
+ redirect_to :controller => ''
+ end
+ end
+ end
+ end
+end
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
new file mode 100644
index 000000000..2c9f67586
--- /dev/null
+++ b/app/controllers/admin_controller.rb
@@ -0,0 +1,56 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class AdminController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ helper :sort
+ include SortHelper
+
+ def index
+ end
+
+ def projects
+ sort_init 'name', 'asc'
+ sort_update
+ @project_count = Project.count
+ @project_pages = Paginator.new self, @project_count,
+ 15,
+ @params['page']
+ @projects = Project.find :all, :order => sort_clause,
+ :limit => @project_pages.items_per_page,
+ :offset => @project_pages.current.offset
+
+ render :action => "projects", :layout => false if request.xhr?
+ end
+
+ def mail_options
+ @actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || []
+ if request.post?
+ @actions.each { |a|
+ a.mail_enabled = (params[:action_ids] || []).include? a.id.to_s
+ a.save
+ }
+ flash.now[:notice] = l(:notice_successful_update)
+ end
+ end
+
+ def info
+ @adapter_name = ActiveRecord::Base.connection.adapter_name
+ end
+end
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
new file mode 100644
index 000000000..3bebf4de5
--- /dev/null
+++ b/app/controllers/application.rb
@@ -0,0 +1,126 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class ApplicationController < ActionController::Base
+ before_filter :check_if_login_required, :set_localization
+
+ def logged_in_user=(user)
+ @logged_in_user = user
+ session[:user_id] = (user ? user.id : nil)
+ end
+
+ def logged_in_user
+ if session[:user_id]
+ @logged_in_user ||= User.find(session[:user_id], :include => :memberships)
+ else
+ nil
+ end
+ end
+
+ # check if login is globally required to access the application
+ def check_if_login_required
+ require_login if $RDM_LOGIN_REQUIRED
+ end
+
+ def set_localization
+ lang = begin
+ if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym
+ self.logged_in_user.language
+ elsif request.env['HTTP_ACCEPT_LANGUAGE']
+ accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
+ if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
+ accept_lang
+ end
+ end
+ rescue
+ nil
+ end || $RDM_DEFAULT_LANG
+ set_language_if_valid(lang)
+ end
+
+ def require_login
+ unless self.logged_in_user
+ store_location
+ redirect_to :controller => "account", :action => "login"
+ return false
+ end
+ true
+ end
+
+ def require_admin
+ return unless require_login
+ unless self.logged_in_user.admin?
+ render :nothing => true, :status => 403
+ return false
+ end
+ true
+ end
+
+ # authorizes the user for the requested action.
+ def authorize
+ # check if action is allowed on public projects
+ if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ @params[:controller], @params[:action] ]
+ return true
+ end
+ # if action is not public, force login
+ return unless require_login
+ # admin is always authorized
+ return true if self.logged_in_user.admin?
+ # if not admin, check membership permission
+ @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id])
+ if @user_membership and Permission.allowed_to_role( "%s/%s" % [ @params[:controller], @params[:action] ], @user_membership.role_id )
+ return true
+ end
+ render :nothing => true, :status => 403
+ false
+ end
+
+ # store current uri in session.
+ # return to this location by calling redirect_back_or_default
+ def store_location
+ session[:return_to] = @request.request_uri
+ end
+
+ # move to the last store_location call or to the passed default one
+ def redirect_back_or_default(default)
+ if session[:return_to].nil?
+ redirect_to default
+ else
+ redirect_to_url session[:return_to]
+ session[:return_to] = nil
+ end
+ end
+
+ # qvalues http header parser
+ # code taken from webrick
+ def parse_qvalues(value)
+ tmp = []
+ if value
+ parts = value.split(/,\s*/)
+ parts.each {|part|
+ if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
+ val = m[1]
+ q = (m[2] or 1).to_f
+ tmp.push([val, q])
+ end
+ }
+ tmp = tmp.sort_by{|val, q| -q}
+ tmp.collect!{|val, q| val}
+ end
+ return tmp
+ end
+end \ No newline at end of file
diff --git a/app/controllers/auth_sources_controller.rb b/app/controllers/auth_sources_controller.rb
new file mode 100644
index 000000000..86b58d365
--- /dev/null
+++ b/app/controllers/auth_sources_controller.rb
@@ -0,0 +1,83 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class AuthSourcesController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ def list
+ @auth_source_pages, @auth_sources = paginate :auth_sources, :per_page => 10
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ def new
+ @auth_source = AuthSourceLdap.new
+ end
+
+ def create
+ @auth_source = AuthSourceLdap.new(params[:auth_source])
+ if @auth_source.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list'
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @auth_source = AuthSource.find(params[:id])
+ end
+
+ def update
+ @auth_source = AuthSource.find(params[:id])
+ if @auth_source.update_attributes(params[:auth_source])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list'
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def test_connection
+ @auth_method = AuthSource.find(params[:id])
+ begin
+ @auth_method.test_connection
+ rescue => text
+ flash[:notice] = text
+ end
+ flash[:notice] ||= l(:notice_successful_connection)
+ redirect_to :action => 'list'
+ end
+
+ def destroy
+ @auth_source = AuthSource.find(params[:id])
+ unless @auth_source.users.find(:first)
+ @auth_source.destroy
+ flash[:notice] = l(:notice_successful_delete)
+ end
+ redirect_to :action => 'list'
+ end
+end
diff --git a/app/controllers/custom_fields_controller.rb b/app/controllers/custom_fields_controller.rb
new file mode 100644
index 000000000..bfa152fd1
--- /dev/null
+++ b/app/controllers/custom_fields_controller.rb
@@ -0,0 +1,71 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class CustomFieldsController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ def list
+ @custom_field_pages, @custom_fields = paginate :custom_fields, :per_page => 15
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ def new
+ case params[:type]
+ when "IssueCustomField"
+ @custom_field = IssueCustomField.new(params[:custom_field])
+ @custom_field.trackers = Tracker.find(params[:tracker_ids]) if params[:tracker_ids]
+ when "UserCustomField"
+ @custom_field = UserCustomField.new(params[:custom_field])
+ when "ProjectCustomField"
+ @custom_field = ProjectCustomField.new(params[:custom_field])
+ else
+ redirect_to :action => 'list'
+ return
+ end
+ if request.post? and @custom_field.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list'
+ end
+ @trackers = Tracker.find(:all)
+ end
+
+ def edit
+ @custom_field = CustomField.find(params[:id])
+ if request.post? and @custom_field.update_attributes(params[:custom_field])
+ if @custom_field.is_a? IssueCustomField
+ @custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
+ end
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list'
+ end
+ @trackers = Tracker.find(:all)
+ end
+
+ def destroy
+ CustomField.find(params[:id]).destroy
+ redirect_to :action => 'list'
+ rescue
+ flash[:notice] = "Unable to delete custom field"
+ redirect_to :action => 'list'
+ end
+end
diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb
new file mode 100644
index 000000000..3107b3ed1
--- /dev/null
+++ b/app/controllers/documents_controller.rb
@@ -0,0 +1,68 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class DocumentsController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def show
+ @attachments = @document.attachments.find(:all, :order => "created_on DESC")
+ end
+
+ def edit
+ @categories = Enumeration::get_values('DCAT')
+ if request.post? and @document.update_attributes(params[:document])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'show', :id => @document
+ end
+ end
+
+ def destroy
+ @document.destroy
+ redirect_to :controller => 'projects', :action => 'list_documents', :id => @project
+ end
+
+ def download
+ @attachment = @document.attachments.find(params[:attachment_id])
+ @attachment.increment_download
+ send_file @attachment.diskfile, :filename => @attachment.filename
+ rescue
+ flash.now[:notice] = l(:notice_file_not_found)
+ render :text => "", :layout => true, :status => 404
+ end
+
+ def add_attachment
+ # Save the attachment
+ if params[:attachment][:file].size > 0
+ @attachment = @document.attachments.build(params[:attachment])
+ @attachment.author_id = self.logged_in_user.id if self.logged_in_user
+ @attachment.save
+ end
+ redirect_to :action => 'show', :id => @document
+ end
+
+ def destroy_attachment
+ @document.attachments.find(params[:attachment_id]).destroy
+ redirect_to :action => 'show', :id => @document
+ end
+
+private
+ def find_project
+ @document = Document.find(params[:id])
+ @project = @document.project
+ end
+end
diff --git a/app/controllers/enumerations_controller.rb b/app/controllers/enumerations_controller.rb
new file mode 100644
index 000000000..8e5be0a20
--- /dev/null
+++ b/app/controllers/enumerations_controller.rb
@@ -0,0 +1,70 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class EnumerationsController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ def index
+ list
+ render :action => 'list'
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ def list
+ end
+
+ def new
+ @enumeration = Enumeration.new(:opt => params[:opt])
+ end
+
+ def create
+ @enumeration = Enumeration.new(params[:enumeration])
+ if @enumeration.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list', :opt => @enumeration.opt
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @enumeration = Enumeration.find(params[:id])
+ end
+
+ def update
+ @enumeration = Enumeration.find(params[:id])
+ if @enumeration.update_attributes(params[:enumeration])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list', :opt => @enumeration.opt
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def destroy
+ Enumeration.find(params[:id]).destroy
+ flash[:notice] = l(:notice_successful_delete)
+ redirect_to :action => 'list'
+ rescue
+ flash[:notice] = "Unable to delete enumeration"
+ redirect_to :action => 'list'
+ end
+end
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
new file mode 100644
index 000000000..32d822993
--- /dev/null
+++ b/app/controllers/help_controller.rb
@@ -0,0 +1,47 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class HelpController < ApplicationController
+
+ skip_before_filter :check_if_login_required
+ before_filter :load_help_config
+
+ # displays help page for the requested controller/action
+ def index
+ # select help page to display
+ if @params[:ctrl] and @help_config['pages'][@params[:ctrl]]
+ if @params[:page] and @help_config['pages'][@params[:ctrl]][@params[:page]]
+ template = @help_config['pages'][@params[:ctrl]][@params[:page]]
+ else
+ template = @help_config['pages'][@params[:ctrl]]['index']
+ end
+ end
+ # choose language according to available help translations
+ lang = (@help_config['langs'].include? current_language.to_s) ? current_language.to_s : @help_config['langs'].first
+
+ if template
+ redirect_to "/manual/#{lang}/#{template}"
+ else
+ redirect_to "/manual/#{lang}/"
+ end
+ end
+
+private
+ def load_help_config
+ @help_config = YAML::load(File.open("#{RAILS_ROOT}/config/help.yml"))
+ end
+end
diff --git a/app/controllers/issue_categories_controller.rb b/app/controllers/issue_categories_controller.rb
new file mode 100644
index 000000000..965a15e78
--- /dev/null
+++ b/app/controllers/issue_categories_controller.rb
@@ -0,0 +1,42 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class IssueCategoriesController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def edit
+ if request.post? and @category.update_attributes(params[:category])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ end
+ end
+
+ def destroy
+ @category.destroy
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ rescue
+ flash[:notice] = "Categorie can't be deleted"
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ end
+
+private
+ def find_project
+ @category = IssueCategory.find(params[:id])
+ @project = @category.project
+ end
+end
diff --git a/app/controllers/issue_statuses_controller.rb b/app/controllers/issue_statuses_controller.rb
new file mode 100644
index 000000000..18ca9c76d
--- /dev/null
+++ b/app/controllers/issue_statuses_controller.rb
@@ -0,0 +1,69 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class IssueStatusesController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ def list
+ @issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 10
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ def new
+ @issue_status = IssueStatus.new
+ end
+
+ def create
+ @issue_status = IssueStatus.new(params[:issue_status])
+ if @issue_status.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list'
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @issue_status = IssueStatus.find(params[:id])
+ end
+
+ def update
+ @issue_status = IssueStatus.find(params[:id])
+ if @issue_status.update_attributes(params[:issue_status])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list'
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def destroy
+ IssueStatus.find(params[:id]).destroy
+ redirect_to :action => 'list'
+ rescue
+ flash[:notice] = "Unable to delete issue status"
+ redirect_to :action => 'list'
+ end
+
+
+end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
new file mode 100644
index 000000000..94e036ab3
--- /dev/null
+++ b/app/controllers/issues_controller.rb
@@ -0,0 +1,145 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class IssuesController < ApplicationController
+ layout 'base', :except => :export_pdf
+ before_filter :find_project, :authorize
+
+ helper :custom_fields
+ include CustomFieldsHelper
+ helper :ifpdf
+ include IfpdfHelper
+
+ def show
+ @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
+ @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
+ @journals_count = @issue.journals.count
+ @journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc")
+ end
+
+ def history
+ @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "journals.created_on desc")
+ @journals_count = @journals.length
+ end
+
+ def export_pdf
+ @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
+ @options_for_rfpdf ||= {}
+ @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
+ end
+
+ def edit
+ @priorities = Enumeration::get_values('IPRI')
+ if request.get?
+ @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
+ else
+ begin
+ @issue.init_journal(self.logged_in_user)
+ # Retrieve custom fields and values
+ @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
+ @issue.custom_values = @custom_values
+ @issue.attributes = params[:issue]
+ if @issue.save
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'show', :id => @issue
+ end
+ rescue ActiveRecord::StaleObjectError
+ # Optimistic locking exception
+ flash[:notice] = l(:notice_locking_conflict)
+ end
+ end
+ end
+
+ def add_note
+ unless params[:notes].empty?
+ journal = @issue.init_journal(self.logged_in_user, params[:notes])
+ #@history = @issue.histories.build(params[:history])
+ #@history.author_id = self.logged_in_user.id if self.logged_in_user
+ #@history.status = @issue.status
+ if @issue.save
+ flash[:notice] = l(:notice_successful_update)
+ Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
+ redirect_to :action => 'show', :id => @issue
+ return
+ end
+ end
+ show
+ render :action => 'show'
+ end
+
+ def change_status
+ #@history = @issue.histories.build(params[:history])
+ @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
+ @new_status = IssueStatus.find(params[:new_status_id])
+ if params[:confirm]
+ begin
+ #@history.author_id = self.logged_in_user.id if self.logged_in_user
+ #@issue.status = @history.status
+ #@issue.fixed_version_id = (params[:issue][:fixed_version_id])
+ #@issue.assigned_to_id = (params[:issue][:assigned_to_id])
+ #@issue.done_ratio = (params[:issue][:done_ratio])
+ #@issue.lock_version = (params[:issue][:lock_version])
+ journal = @issue.init_journal(self.logged_in_user, params[:notes])
+ @issue.status = @new_status
+ if @issue.update_attributes(params[:issue])
+ flash[:notice] = l(:notice_successful_update)
+ Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
+ redirect_to :action => 'show', :id => @issue
+ end
+ rescue ActiveRecord::StaleObjectError
+ # Optimistic locking exception
+ flash[:notice] = l(:notice_locking_conflict)
+ end
+ end
+ @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
+ end
+
+ def destroy
+ @issue.destroy
+ redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
+ end
+
+ def add_attachment
+ # Save the attachments
+ params[:attachments].each { |a|
+ @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
+ @attachment.save
+ } if params[:attachments] and params[:attachments].is_a? Array
+ redirect_to :action => 'show', :id => @issue
+ end
+
+ def destroy_attachment
+ @issue.attachments.find(params[:attachment_id]).destroy
+ redirect_to :action => 'show', :id => @issue
+ end
+
+ # Send the file in stream mode
+ def download
+ @attachment = @issue.attachments.find(params[:attachment_id])
+ send_file @attachment.diskfile, :filename => @attachment.filename
+ rescue
+ flash.now[:notice] = l(:notice_file_not_found)
+ render :text => "", :layout => true, :status => 404
+ end
+
+private
+ def find_project
+ @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
+ @project = @issue.project
+ @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
+ end
+end
diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb
new file mode 100644
index 000000000..be3f717d1
--- /dev/null
+++ b/app/controllers/members_controller.rb
@@ -0,0 +1,41 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class MembersController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def edit
+ if request.post? and @member.update_attributes(params[:member])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ end
+ end
+
+ def destroy
+ @member.destroy
+ flash[:notice] = l(:notice_successful_delete)
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ end
+
+private
+ def find_project
+ @member = Member.find(params[:id])
+ @project = @member.project
+ end
+
+end
diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb
new file mode 100644
index 000000000..ff12b74d7
--- /dev/null
+++ b/app/controllers/my_controller.rb
@@ -0,0 +1,131 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class MyController < ApplicationController
+ layout 'base'
+ before_filter :require_login
+
+ BLOCKS = { 'issues_assigned_to_me' => :label_assigned_to_me_issues,
+ 'issues_reported_by_me' => :label_reported_issues,
+ 'latest_news' => :label_news_latest,
+ 'calendar' => :label_calendar,
+ 'documents' => :label_document_plural
+ }.freeze
+
+ verify :xhr => true,
+ :session => :page_layout,
+ :only => [:add_block, :remove_block, :order_blocks]
+
+ def index
+ page
+ render :action => 'page'
+ end
+
+ # Show user's page
+ def page
+ @user = self.logged_in_user
+ @blocks = @user.pref[:my_page_layout] || { 'left' => ['issues_assigned_to_me'], 'right' => ['issues_reported_by_me'] }
+ end
+
+ # Edit user's account
+ def account
+ @user = self.logged_in_user
+ @pref = @user.pref
+ @user.attributes = params[:user]
+ @user.pref.attributes = params[:pref]
+ if request.post? and @user.save
+ set_localization
+ flash.now[:notice] = l(:notice_account_updated)
+ self.logged_in_user.reload
+ end
+ end
+
+ # Change user's password
+ def change_password
+ @user = self.logged_in_user
+ flash[:notice] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
+ if @user.check_password?(@params[:password])
+ @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
+ if @user.save
+ flash[:notice] = l(:notice_account_password_updated)
+ else
+ render :action => 'account'
+ return
+ end
+ else
+ flash[:notice] = l(:notice_account_wrong_password)
+ end
+ redirect_to :action => 'account'
+ end
+
+ # User's page layout configuration
+ def page_layout
+ @user = self.logged_in_user
+ @blocks = @user.pref[:my_page_layout] || { 'left' => ['issues_assigned_to_me'], 'right' => ['issues_reported_by_me'] }
+ session[:page_layout] = @blocks
+ %w(top left right).each {|f| session[:page_layout][f] ||= [] }
+ @block_options = []
+ BLOCKS.each {|k, v| @block_options << [l(v), k]}
+ end
+
+ # Add a block to user's page
+ # The block is added on top of the page
+ # params[:block] : id of the block to add
+ def add_block
+ @user = self.logged_in_user
+ block = params[:block]
+ # remove if already present in a group
+ %w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
+ # add it on top
+ session[:page_layout]['top'].unshift block
+ render :partial => "block", :locals => {:user => @user, :block_name => block}
+ end
+
+ # Remove a block to user's page
+ # params[:block] : id of the block to remove
+ def remove_block
+ block = params[:block]
+ # remove block in all groups
+ %w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
+ render :nothing => true
+ end
+
+ # Change blocks order on user's page
+ # params[:group] : group to order (top, left or right)
+ # params[:list-(top|left|right)] : array of block ids of the group
+ def order_blocks
+ group = params[:group]
+ group_items = params["list-#{group}"]
+ if group_items and group_items.is_a? Array
+ # remove group blocks if they are presents in other groups
+ %w(top left right).each {|f|
+ session[:page_layout][f] = (session[:page_layout][f] || []) - group_items
+ }
+ session[:page_layout][group] = group_items
+ end
+ render :nothing => true
+ end
+
+ # Save user's page layout
+ def page_layout_save
+ @user = self.logged_in_user
+ @user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout]
+ @user.pref.save
+ session[:page_layout] = nil
+ redirect_to :action => 'page'
+ end
+end
diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb
new file mode 100644
index 000000000..b50b59dc0
--- /dev/null
+++ b/app/controllers/news_controller.rb
@@ -0,0 +1,42 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class NewsController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def show
+ end
+
+ def edit
+ if request.post? and @news.update_attributes(params[:news])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'show', :id => @news
+ end
+ end
+
+ def destroy
+ @news.destroy
+ redirect_to :controller => 'projects', :action => 'list_news', :id => @project
+ end
+
+private
+ def find_project
+ @news = News.find(params[:id])
+ @project = @news.project
+ end
+end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
new file mode 100644
index 000000000..c968800c3
--- /dev/null
+++ b/app/controllers/projects_controller.rb
@@ -0,0 +1,469 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class ProjectsController < ApplicationController
+ layout 'base', :except => :export_issues_pdf
+ before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
+ before_filter :require_admin, :only => [ :add, :destroy ]
+
+ helper :sort
+ include SortHelper
+ helper :search_filter
+ include SearchFilterHelper
+ helper :custom_fields
+ include CustomFieldsHelper
+ helper :ifpdf
+ include IfpdfHelper
+ helper IssuesHelper
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ # Lists public projects
+ def list
+ sort_init 'name', 'asc'
+ sort_update
+ @project_count = Project.count(["is_public=?", true])
+ @project_pages = Paginator.new self, @project_count,
+ 15,
+ @params['page']
+ @projects = Project.find :all, :order => sort_clause,
+ :conditions => ["is_public=?", true],
+ :limit => @project_pages.items_per_page,
+ :offset => @project_pages.current.offset
+
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ # Add a new project
+ def add
+ @custom_fields = IssueCustomField.find(:all)
+ @root_projects = Project.find(:all, :conditions => "parent_id is null")
+ @project = Project.new(params[:project])
+ if request.get?
+ @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
+ else
+ @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
+ @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
+ @project.custom_values = @custom_values
+ if @project.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :controller => 'admin', :action => 'projects'
+ end
+ end
+ end
+
+ # Show @project
+ def show
+ @custom_values = @project.custom_values.find(:all, :include => :custom_field)
+ @members = @project.members.find(:all, :include => [:user, :role])
+ @subprojects = @project.children if @project.children_count > 0
+ @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
+ @trackers = Tracker.find(:all)
+ end
+
+ def settings
+ @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
+ @custom_fields = IssueCustomField::find_all
+ @issue_category ||= IssueCategory.new
+ @member ||= @project.members.new
+ @roles = Role.find_all
+ @users = User.find_all - @project.members.find(:all, :include => :user).collect{|m| m.user }
+ @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
+ end
+
+ # Edit @project
+ def edit
+ if request.post?
+ @project.custom_fields = IssueCustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
+ if params[:custom_fields]
+ @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
+ @project.custom_values = @custom_values
+ end
+ if @project.update_attributes(params[:project])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'settings', :id => @project
+ else
+ settings
+ render :action => 'settings'
+ end
+ end
+ end
+
+ # Delete @project
+ def destroy
+ if request.post? and params[:confirm]
+ @project.destroy
+ redirect_to :controller => 'admin', :action => 'projects'
+ end
+ end
+
+ # Add a new issue category to @project
+ def add_issue_category
+ if request.post?
+ @issue_category = @project.issue_categories.build(params[:issue_category])
+ if @issue_category.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'settings', :id => @project
+ else
+ settings
+ render :action => 'settings'
+ end
+ end
+ end
+
+ # Add a new version to @project
+ def add_version
+ @version = @project.versions.build(params[:version])
+ if request.post? and @version.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'settings', :id => @project
+ end
+ end
+
+ # Add a new member to @project
+ def add_member
+ @member = @project.members.build(params[:member])
+ if request.post?
+ if @member.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'settings', :id => @project
+ else
+ settings
+ render :action => 'settings'
+ end
+ end
+ end
+
+ # Show members list of @project
+ def list_members
+ @members = @project.members
+ end
+
+ # Add a new document to @project
+ def add_document
+ @categories = Enumeration::get_values('DCAT')
+ @document = @project.documents.build(params[:document])
+ if request.post?
+ # Save the attachment
+ if params[:attachment][:file].size > 0
+ @attachment = @document.attachments.build(params[:attachment])
+ @attachment.author_id = self.logged_in_user.id if self.logged_in_user
+ end
+ if @document.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list_documents', :id => @project
+ end
+ end
+ end
+
+ # Show documents list of @project
+ def list_documents
+ @documents = @project.documents
+ end
+
+ # Add a new issue to @project
+ def add_issue
+ @tracker = Tracker.find(params[:tracker_id])
+ @priorities = Enumeration::get_values('IPRI')
+ @issue = Issue.new(:project => @project, :tracker => @tracker)
+ if request.get?
+ @issue.start_date = Date.today
+ @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
+ else
+ @issue.attributes = params[:issue]
+ @issue.author_id = self.logged_in_user.id if self.logged_in_user
+ # Multiple file upload
+ params[:attachments].each { |a|
+ @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
+ } if params[:attachments] and params[:attachments].is_a? Array
+ @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
+ @issue.custom_values = @custom_values
+ if @issue.save
+ flash[:notice] = l(:notice_successful_create)
+ Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
+ redirect_to :action => 'list_issues', :id => @project
+ end
+ end
+ end
+
+ # Show filtered/sorted issues list of @project
+ def list_issues
+ sort_init 'issues.id', 'desc'
+ sort_update
+
+ search_filter_init_list_issues
+ search_filter_update if params[:set_filter]
+
+ @results_per_page_options = [ 15, 25, 50, 100 ]
+ if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
+ @results_per_page = params[:per_page].to_i
+ session[:results_per_page] = @results_per_page
+ else
+ @results_per_page = session[:results_per_page] || 25
+ end
+
+ @issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause)
+ @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page']
+ @issues = Issue.find :all, :order => sort_clause,
+ :include => [ :author, :status, :tracker, :project ],
+ :conditions => search_filter_clause,
+ :limit => @issue_pages.items_per_page,
+ :offset => @issue_pages.current.offset
+
+ render :layout => false if request.xhr?
+ end
+
+ # Export filtered/sorted issues list to CSV
+ def export_issues_csv
+ sort_init 'issues.id', 'desc'
+ sort_update
+
+ search_filter_init_list_issues
+
+ @issues = Issue.find :all, :order => sort_clause,
+ :include => [ :author, :status, :tracker, :project, :custom_values ],
+ :conditions => search_filter_clause
+
+ ic = Iconv.new('ISO-8859-1', 'UTF-8')
+ export = StringIO.new
+ CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
+ # csv header fields
+ headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
+ for custom_field in @project.all_custom_fields
+ headers << custom_field.name
+ end
+ csv << headers.collect {|c| ic.iconv(c) }
+ # csv lines
+ @issues.each do |issue|
+ fields = [issue.id, issue.status.name, issue.tracker.name, issue.subject, issue.author.display_name, l_datetime(issue.created_on), l_datetime(issue.updated_on)]
+ for custom_field in @project.all_custom_fields
+ fields << (show_value issue.custom_value_for(custom_field))
+ end
+ csv << fields.collect {|c| ic.iconv(c.to_s) }
+ end
+ end
+ export.rewind
+ send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
+ end
+
+ # Export filtered/sorted issues to PDF
+ def export_issues_pdf
+ sort_init 'issues.id', 'desc'
+ sort_update
+
+ search_filter_init_list_issues
+
+ @issues = Issue.find :all, :order => sort_clause,
+ :include => [ :author, :status, :tracker, :project, :custom_values ],
+ :conditions => search_filter_clause
+
+ @options_for_rfpdf ||= {}
+ @options_for_rfpdf[:file_name] = "export.pdf"
+ end
+
+ def move_issues
+ @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
+ redirect_to :action => 'list_issues', :id => @project and return unless @issues
+ @projects = []
+ # find projects to which the user is allowed to move the issue
+ @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
+ # issue can be moved to any tracker
+ @trackers = Tracker.find(:all)
+ if request.post? and params[:new_project_id] and params[:new_tracker_id]
+ new_project = Project.find(params[:new_project_id])
+ new_tracker = Tracker.find(params[:new_tracker_id])
+ @issues.each { |i|
+ # category is project dependent
+ i.category = nil unless i.project_id == new_project.id
+ # move the issue
+ i.project = new_project
+ i.tracker = new_tracker
+ i.save
+ }
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list_issues', :id => @project
+ end
+ end
+
+ # Add a news to @project
+ def add_news
+ @news = News.new(:project => @project)
+ if request.post?
+ @news.attributes = params[:news]
+ @news.author_id = self.logged_in_user.id if self.logged_in_user
+ if @news.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list_news', :id => @project
+ end
+ end
+ end
+
+ # Show news list of @project
+ def list_news
+ @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
+ render :action => "list_news", :layout => false if request.xhr?
+ end
+
+ def add_file
+ if request.post?
+ # Save the attachment
+ if params[:attachment][:file].size > 0
+ @attachment = @project.versions.find(params[:version_id]).attachments.build(params[:attachment])
+ @attachment.author_id = self.logged_in_user.id if self.logged_in_user
+ if @attachment.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :controller => 'projects', :action => 'list_files', :id => @project
+ end
+ end
+ end
+ @versions = @project.versions
+ end
+
+ def list_files
+ @versions = @project.versions
+ end
+
+ # Show changelog for @project
+ def changelog
+ @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
+ if request.get?
+ @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
+ else
+ @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
+ end
+ @selected_tracker_ids ||= []
+ @fixed_issues = @project.issues.find(:all,
+ :include => [ :fixed_version, :status, :tracker ],
+ :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
+ :order => "versions.effective_date DESC, issues.id DESC"
+ ) unless @selected_tracker_ids.empty?
+ @fixed_issues ||= []
+ end
+
+ def activity
+ if params[:year] and params[:year].to_i > 1900
+ @year = params[:year].to_i
+ if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
+ @month = params[:month].to_i
+ end
+ end
+ @year ||= Date.today.year
+ @month ||= Date.today.month
+
+ @date_from = Date.civil(@year, @month, 1)
+ @date_to = (@date_from >> 1)-1
+
+ @events_by_day = {}
+
+ unless params[:show_issues] == "0"
+ @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
+ @events_by_day[i.created_on.to_date] ||= []
+ @events_by_day[i.created_on.to_date] << i
+ }
+ @show_issues = 1
+ end
+
+ unless params[:show_news] == "0"
+ @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to] ).each { |i|
+ @events_by_day[i.created_on.to_date] ||= []
+ @events_by_day[i.created_on.to_date] << i
+ }
+ @show_news = 1
+ end
+
+ unless params[:show_files] == "0"
+ Attachment.find(:all, :joins => "LEFT JOIN versions ON versions.id = attachments.container_id", :conditions => ["attachments.container_type='Version' and versions.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
+ @events_by_day[i.created_on.to_date] ||= []
+ @events_by_day[i.created_on.to_date] << i
+ }
+ @show_files = 1
+ end
+
+ unless params[:show_documents] == "0"
+ Attachment.find(:all, :joins => "LEFT JOIN documents ON documents.id = attachments.container_id", :conditions => ["attachments.container_type='Document' and documents.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
+ @events_by_day[i.created_on.to_date] ||= []
+ @events_by_day[i.created_on.to_date] << i
+ }
+ @show_documents = 1
+ end
+
+ end
+
+ def calendar
+ if params[:year] and params[:year].to_i > 1900
+ @year = params[:year].to_i
+ if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
+ @month = params[:month].to_i
+ end
+ end
+ @year ||= Date.today.year
+ @month ||= Date.today.month
+
+ @date_from = Date.civil(@year, @month, 1)
+ @date_to = (@date_from >> 1)-1
+ # start on monday
+ @date_from = @date_from - (@date_from.cwday-1)
+ # finish on sunday
+ @date_to = @date_to + (7-@date_to.cwday)
+
+ @issues = @project.issues.find(:all, :include => :tracker, :conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to])
+ render :layout => false if request.xhr?
+ end
+
+ def gantt
+ if params[:year] and params[:year].to_i >0
+ @year_from = params[:year].to_i
+ if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
+ @month_from = params[:month].to_i
+ else
+ @month_from = 1
+ end
+ else
+ @month_from ||= (Date.today << 1).month
+ @year_from ||= (Date.today << 1).year
+ end
+
+ @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
+ @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
+
+ @date_from = Date.civil(@year_from, @month_from, 1)
+ @date_to = (@date_from >> @months) - 1
+ @issues = @project.issues.find(:all, :order => "start_date, due_date", :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to])
+
+ if params[:output]=='pdf'
+ @options_for_rfpdf ||= {}
+ @options_for_rfpdf[:file_name] = "gantt.pdf"
+ render :template => "projects/gantt.rfpdf", :layout => false
+ else
+ render :template => "projects/gantt.rhtml"
+ end
+ end
+
+private
+ # Find project of id params[:id]
+ # if not found, redirect to project list
+ # Used as a before_filter
+ def find_project
+ @project = Project.find(params[:id])
+ @html_title = @project.name
+ rescue
+ redirect_to :action => 'list'
+ end
+end
diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb
new file mode 100644
index 000000000..985c937fc
--- /dev/null
+++ b/app/controllers/reports_controller.rb
@@ -0,0 +1,164 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class ReportsController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def issue_report
+ @statuses = IssueStatus.find_all
+
+ case params[:detail]
+ when "tracker"
+ @field = "tracker_id"
+ @rows = Tracker.find_all
+ @data = issues_by_tracker
+ @report_title = l(:field_tracker)
+ render :template => "reports/issue_report_details"
+ when "priority"
+ @field = "priority_id"
+ @rows = Enumeration::get_values('IPRI')
+ @data = issues_by_priority
+ @report_title = l(:field_priority)
+ render :template => "reports/issue_report_details"
+ when "category"
+ @field = "category_id"
+ @rows = @project.issue_categories
+ @data = issues_by_category
+ @report_title = l(:field_category)
+ render :template => "reports/issue_report_details"
+ when "author"
+ @field = "author_id"
+ @rows = @project.members.collect { |m| m.user }
+ @data = issues_by_author
+ @report_title = l(:field_author)
+ render :template => "reports/issue_report_details"
+ else
+ @trackers = Tracker.find(:all)
+ @priorities = Enumeration::get_values('IPRI')
+ @categories = @project.issue_categories
+ @authors = @project.members.collect { |m| m.user }
+ issues_by_tracker
+ issues_by_priority
+ issues_by_category
+ issues_by_author
+ render :template => "reports/issue_report"
+ end
+ end
+
+ def delays
+ @trackers = Tracker.find(:all)
+ if request.get?
+ @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
+ else
+ @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
+ end
+ @selected_tracker_ids ||= []
+ @raw =
+ ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total
+ FROM issue_histories a, issue_histories b, issues i
+ WHERE a.status_id =5
+ AND a.issue_id = b.issue_id
+ AND a.issue_id = i.id
+ AND i.tracker_id in (#{@selected_tracker_ids.join(',')})
+ AND b.id = (
+ SELECT min( c.id )
+ FROM issue_histories c
+ WHERE b.issue_id = c.issue_id )
+ GROUP BY delay") unless @selected_tracker_ids.empty?
+ @raw ||=[]
+
+ @x_from = 0
+ @x_to = 0
+ @y_from = 0
+ @y_to = 0
+ @sum_total = 0
+ @sum_delay = 0
+ @raw.each do |r|
+ @x_to = [r['delay'].to_i, @x_to].max
+ @y_to = [r['total'].to_i, @y_to].max
+ @sum_total = @sum_total + r['total'].to_i
+ @sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i
+ end
+ end
+
+private
+ # Find project of id params[:id]
+ def find_project
+ @project = Project.find(params[:id])
+ end
+
+ def issues_by_tracker
+ @issues_by_tracker ||=
+ ActiveRecord::Base.connection.select_all("select s.id as status_id,
+ s.is_closed as closed,
+ t.id as tracker_id,
+ count(i.id) as total
+ from
+ issues i, issue_statuses s, trackers t
+ where
+ i.status_id=s.id
+ and i.tracker_id=t.id
+ and i.project_id=#{@project.id}
+ group by s.id, s.is_closed, t.id")
+ end
+
+ def issues_by_priority
+ @issues_by_priority ||=
+ ActiveRecord::Base.connection.select_all("select s.id as status_id,
+ s.is_closed as closed,
+ p.id as priority_id,
+ count(i.id) as total
+ from
+ issues i, issue_statuses s, enumerations p
+ where
+ i.status_id=s.id
+ and i.priority_id=p.id
+ and i.project_id=#{@project.id}
+ group by s.id, s.is_closed, p.id")
+ end
+
+ def issues_by_category
+ @issues_by_category ||=
+ ActiveRecord::Base.connection.select_all("select s.id as status_id,
+ s.is_closed as closed,
+ c.id as category_id,
+ count(i.id) as total
+ from
+ issues i, issue_statuses s, issue_categories c
+ where
+ i.status_id=s.id
+ and i.category_id=c.id
+ and i.project_id=#{@project.id}
+ group by s.id, s.is_closed, c.id")
+ end
+
+ def issues_by_author
+ @issues_by_author ||=
+ ActiveRecord::Base.connection.select_all("select s.id as status_id,
+ s.is_closed as closed,
+ a.id as author_id,
+ count(i.id) as total
+ from
+ issues i, issue_statuses s, users a
+ where
+ i.status_id=s.id
+ and i.author_id=a.id
+ and i.project_id=#{@project.id}
+ group by s.id, s.is_closed, a.id")
+ end
+end
diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb
new file mode 100644
index 000000000..e16127b61
--- /dev/null
+++ b/app/controllers/roles_controller.rb
@@ -0,0 +1,84 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class RolesController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ def list
+ @role_pages, @roles = paginate :roles, :per_page => 10
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ def new
+ @role = Role.new(params[:role])
+ if request.post?
+ @role.permissions = Permission.find(@params[:permission_ids]) if @params[:permission_ids]
+ if @role.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list'
+ end
+ end
+ @permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC')
+ end
+
+ def edit
+ @role = Role.find(params[:id])
+ if request.post? and @role.update_attributes(params[:role])
+ @role.permissions = Permission.find(@params[:permission_ids] || [])
+ Permission.allowed_to_role_expired
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list'
+ end
+ @permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC')
+ end
+
+ def destroy
+ @role = Role.find(params[:id])
+ unless @role.members.empty?
+ flash[:notice] = 'Some members have this role. Can\'t delete it.'
+ else
+ @role.destroy
+ end
+ redirect_to :action => 'list'
+ end
+
+ def workflow
+ @role = Role.find_by_id(params[:role_id])
+ @tracker = Tracker.find_by_id(params[:tracker_id])
+
+ if request.post?
+ Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
+ (params[:issue_status] || []).each { |old, news|
+ news.each { |new|
+ @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
+ }
+ }
+ if @role.save
+ flash[:notice] = l(:notice_successful_update)
+ end
+ end
+ @roles = Role.find_all
+ @trackers = Tracker.find_all
+ @statuses = IssueStatus.find(:all, :include => :workflows)
+ end
+end
diff --git a/app/controllers/trackers_controller.rb b/app/controllers/trackers_controller.rb
new file mode 100644
index 000000000..bbfb4f48b
--- /dev/null
+++ b/app/controllers/trackers_controller.rb
@@ -0,0 +1,61 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class TrackersController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :list }
+
+ def list
+ @tracker_pages, @trackers = paginate :trackers, :per_page => 10
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ def new
+ @tracker = Tracker.new(params[:tracker])
+ if request.post? and @tracker.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list'
+ end
+ end
+
+ def edit
+ @tracker = Tracker.find(params[:id])
+ if request.post? and @tracker.update_attributes(params[:tracker])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list'
+ end
+ end
+
+ def destroy
+ @tracker = Tracker.find(params[:id])
+ unless @tracker.issues.empty?
+ flash[:notice] = "This tracker contains issues and can\'t be deleted."
+ else
+ @tracker.destroy
+ end
+ redirect_to :action => 'list'
+ end
+
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 000000000..47d0e51c9
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,92 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class UsersController < ApplicationController
+ layout 'base'
+ before_filter :require_admin
+
+ helper :sort
+ include SortHelper
+ helper :custom_fields
+ include CustomFieldsHelper
+
+ def index
+ list
+ render :action => 'list' unless request.xhr?
+ end
+
+ def list
+ sort_init 'login', 'asc'
+ sort_update
+ @user_count = User.count
+ @user_pages = Paginator.new self, @user_count,
+ 15,
+ @params['page']
+ @users = User.find :all,:order => sort_clause,
+ :limit => @user_pages.items_per_page,
+ :offset => @user_pages.current.offset
+
+ render :action => "list", :layout => false if request.xhr?
+ end
+
+ def add
+ if request.get?
+ @user = User.new(:language => $RDM_DEFAULT_LANG)
+ @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
+ else
+ @user = User.new(params[:user])
+ @user.admin = params[:user][:admin] || false
+ @user.login = params[:user][:login]
+ @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
+ @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
+ @user.custom_values = @custom_values
+ if @user.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'list'
+ end
+ end
+ @auth_sources = AuthSource.find(:all)
+ end
+
+ def edit
+ @user = User.find(params[:id])
+ if request.get?
+ @custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
+ else
+ @user.admin = params[:user][:admin] if params[:user][:admin]
+ @user.login = params[:user][:login] if params[:user][:login]
+ @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
+ if params[:custom_fields]
+ @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
+ @user.custom_values = @custom_values
+ end
+ if @user.update_attributes(params[:user])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'list'
+ end
+ end
+ @auth_sources = AuthSource.find(:all)
+ end
+
+ def destroy
+ User.find(params[:id]).destroy
+ redirect_to :action => 'list'
+ rescue
+ flash[:notice] = "Unable to delete user"
+ redirect_to :action => 'list'
+ end
+end
diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb
new file mode 100644
index 000000000..d1980d74f
--- /dev/null
+++ b/app/controllers/versions_controller.rb
@@ -0,0 +1,57 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class VersionsController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def edit
+ if request.post? and @version.update_attributes(params[:version])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ end
+ end
+
+ def destroy
+ @version.destroy
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ rescue
+ flash[:notice] = "Unable to delete version"
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
+ end
+
+ def download
+ @attachment = @version.attachments.find(params[:attachment_id])
+ @attachment.increment_download
+ send_file @attachment.diskfile, :filename => @attachment.filename
+ rescue
+ flash.now[:notice] = l(:notice_file_not_found)
+ render :text => "", :layout => true, :status => 404
+ end
+
+ def destroy_file
+ @version.attachments.find(params[:attachment_id]).destroy
+ flash[:notice] = l(:notice_successful_delete)
+ redirect_to :controller => 'projects', :action => 'list_files', :id => @project
+ end
+
+private
+ def find_project
+ @version = Version.find(params[:id])
+ @project = @version.project
+ end
+end
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
new file mode 100644
index 000000000..c47198d51
--- /dev/null
+++ b/app/controllers/welcome_controller.rb
@@ -0,0 +1,25 @@
+# redMine - project management software
+# Copyright (C) 2006 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.
+
+class WelcomeController < ApplicationController
+ layout 'base'
+
+ def index
+ @news = News.latest
+ @projects = Project.latest
+ end
+end