diff --git a/redmine/app/controllers/account_controller.rb b/redmine/app/controllers/account_controller.rb index d5c98f58c..54e0ef704 100644 --- a/redmine/app/controllers/account_controller.rb +++ b/redmine/app/controllers/account_controller.rb @@ -16,31 +16,30 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class AccountController < ApplicationController - layout 'base' + layout 'base' + # prevents login action to be filtered by check_if_login_required application scope filter skip_before_filter :check_if_login_required, :only => :login - before_filter :require_login, :except => [:show, :login] + before_filter :require_login, :except => [:show, :login] - def show - @user = User.find(params[:id]) - end - - # Login request and validation - def login - if request.get? - session[:user] = nil - @user = User.new - else - @user = User.new(params[:user]) - logged_in_user = @user.try_to_login - if logged_in_user - session[:user] = logged_in_user - redirect_back_or_default :controller => 'account', :action => 'my_page' - else - flash[:notice] = _('Invalid user/password') - end - end - end + def show + @user = User.find(params[:id]) + end + + # Login request and validation + def login + if request.get? + session[:user] = nil + else + logged_in_user = User.try_to_login(params[:login], params[:password]) + if logged_in_user + session[:user] = logged_in_user + redirect_back_or_default :controller => 'account', :action => 'my_page' + else + flash[:notice] = _('Invalid user/password') + end + end + end # Log out current user and redirect to welcome page def logout @@ -64,20 +63,15 @@ class AccountController < ApplicationController end end - # Change current user's password - def change_password - @user = User.find(session[:user].id) - if @user.check_password?(@params[:old_password]) - if @params[:new_password] == @params[:new_password_confirmation] - if @user.change_password(@params[:old_password], @params[:new_password]) - flash[:notice] = 'Password was successfully updated.' - end - else - flash[:notice] = 'Password confirmation doesn\'t match!' - end - else - flash[:notice] = 'Wrong password' - end - render :action => 'my_account' - end + # Change current user's password + def change_password + @user = User.find(session[:user].id) + if @user.check_password?(@params[:password]) + @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] + flash[:notice] = 'Password was successfully updated.' if @user.save + else + flash[:notice] = 'Wrong password' + end + render :action => 'my_account' + end end diff --git a/redmine/app/controllers/admin_controller.rb b/redmine/app/controllers/admin_controller.rb index fa34baff1..68d08137d 100644 --- a/redmine/app/controllers/admin_controller.rb +++ b/redmine/app/controllers/admin_controller.rb @@ -16,26 +16,32 @@ # 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 + layout 'base' + before_filter :require_admin - def index - end + helper :sort + include SortHelper + + def index + end def projects - sort_init 'projects.name', 'asc' - sort_update - @project_pages, @projects = paginate :projects, :per_page => 15, :order => sort_clause + 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 end - + def mail_options - @actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || [] + @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.mail_enabled = (params[:action_ids] || []).include? a.id.to_s a.save } flash[:notice] = "Mail options were successfully updated." @@ -44,6 +50,5 @@ class AdminController < ApplicationController def info @adapter_name = ActiveRecord::Base.connection.adapter_name - end - + end end diff --git a/redmine/app/controllers/application.rb b/redmine/app/controllers/application.rb index a9dd6b80e..9cc37cfa9 100644 --- a/redmine/app/controllers/application.rb +++ b/redmine/app/controllers/application.rb @@ -24,63 +24,73 @@ class ApplicationController < ActionController::Base end def set_localization - Localization.lang = session[:user].nil? ? RDM_DEFAULT_LANG : (session[:user].language || RDM_DEFAULT_LANG) + Localization.lang = begin + if session[:user] + session[:user].language + elsif request.env['HTTP_ACCEPT_LANGUAGE'] + accept_lang = HTTPUtils.parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first + if Localization.langs.collect{ |l| l[1] }.include? accept_lang + accept_lang + end + end + rescue + nil + end || RDM_DEFAULT_LANG end - def require_login - unless session[:user] - store_location - redirect_to(:controller => "account", :action => "login") - end - end + def require_login + unless session[:user] + store_location + redirect_to(:controller => "account", :action => "login") + end + end - def require_admin - if session[:user].nil? - store_location - redirect_to(:controller => "account", :action => "login") - else - unless session[:user].admin? - flash[:notice] = "Acces not allowed" - redirect_to(:controller => "projects", :action => "list") - end - end - end + def require_admin + if session[:user].nil? + store_location + redirect_to(:controller => "account", :action => "login") + else + unless session[:user].admin? + flash[:notice] = "Acces not allowed" + redirect_to(:controller => "projects", :action => "list") + end + end + end - # authorizes the user for the requested action. - def authorize + # authorizes the user for the requested action. + def authorize # check if action is allowed on public projects - if @project.public? and Permission.allowed_to_public "%s/%s" % [ @params[:controller], @params[:action] ] + if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ @params[:controller], @params[:action] ] return true end - # if user is not logged in, he is redirect to login form - unless session[:user] - store_location - redirect_to(:controller => "account", :action => "login") - return false - end - # check if user is authorized + # if user not logged in, redirect to login form + unless session[:user] + store_location + redirect_to(:controller => "account", :action => "login") + return false + end + # if logged in, check if authorized if session[:user].admin? or Permission.allowed_to_role( "%s/%s" % [ @params[:controller], @params[:action] ], session[:user].role_for_project(@project.id) ) return true - end + end flash[:notice] = "Acces denied" redirect_to(:controller => "") - return false - end + false + end - # store current uri in the session. - # we can 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 - + # 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 end \ No newline at end of file diff --git a/redmine/app/controllers/help_controller.rb b/redmine/app/controllers/help_controller.rb index 4b555d599..e51d077a1 100644 --- a/redmine/app/controllers/help_controller.rb +++ b/redmine/app/controllers/help_controller.rb @@ -16,28 +16,32 @@ # 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 - def index - if @params[:ctrl] and @help_config[@params[:ctrl]] - if @params[:page] and @help_config[@params[:ctrl]][@params[:page]] - template = @help_config[@params[:ctrl]][@params[:page]] - else - template = @help_config[@params[:ctrl]]['index'] - end - end - - if template - redirect_to "/manual/#{template}" - else - redirect_to "/manual/" + 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 - end + # choose language according to available help translations + lang = (@help_config['langs'].include? Localization.lang) ? Localization.lang : @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 + def load_help_config + @help_config = YAML::load(File.open("#{RAILS_ROOT}/config/help.yml")) + end end diff --git a/redmine/app/controllers/projects_controller.rb b/redmine/app/controllers/projects_controller.rb index a9737aa1c..2bef221b1 100644 --- a/redmine/app/controllers/projects_controller.rb +++ b/redmine/app/controllers/projects_controller.rb @@ -32,58 +32,62 @@ class ProjectsController < ApplicationController render :action => 'list' end - # Lists public projects - def list - sort_init 'projects.name', 'asc' - sort_update - @project_count = Project.count(["public=?", true]) - @project_pages = Paginator.new self, @project_count, + # 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 => ["public=?", true], + @projects = Project.find :all, :order => sort_clause, + :conditions => ["is_public=?", true], :limit => @project_pages.items_per_page, :offset => @project_pages.current.offset end # Add a new project - def add - @custom_fields = CustomField::find_all - @project = Project.new(params[:project]) - if request.post? - @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids] - if @project.save - flash[:notice] = 'Project was successfully created.' - redirect_to :controller => 'admin', :action => 'projects' - end - end - end + def add + @custom_fields = CustomField::find_all + @root_projects = Project::find(:all, :conditions => "parent_id is null") + @project = Project.new(params[:project]) + if request.post? + @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids] + if @project.save + flash[:notice] = 'Project was successfully created.' + redirect_to :controller => 'admin', :action => 'projects' + end + end + end - # Show @project - def show - @members = @project.members.find(:all, :include => [:user, :role]) - end + # Show @project + def show + @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") + end def settings - @custom_fields = CustomField::find_all - @issue_category ||= IssueCategory.new + @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id]) + @custom_fields = CustomField::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 } end - # Edit @project - def edit - if request.post? - @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids] - if @project.update_attributes(params[:project]) - flash[:notice] = 'Project was successfully updated.' - redirect_to :action => 'settings', :id => @project + # Edit @project + def edit + if request.post? + @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids] + if @project.update_attributes(params[:project]) + flash[:notice] = 'Project was successfully updated.' + redirect_to :action => 'settings', :id => @project else settings render :action => 'settings' - end - end + end + end end # Delete @project @@ -181,7 +185,7 @@ class ProjectsController < ApplicationController end end - # Show issues list of @project + # Show filtered/sorted issues list of @project def list_issues sort_init 'issues.id', 'desc' sort_update @@ -189,10 +193,10 @@ class ProjectsController < ApplicationController search_filter_init_list_issues search_filter_update if params[:set_filter] or request.post? - @issue_count = Issue.count(:include => :status, :conditions => search_filter_clause) + @issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause) @issue_pages = Paginator.new self, @issue_count, 15, @params['page'] @issues = Issue.find :all, :order => sort_clause, - :include => [ :author, :status, :tracker ], + :include => [ :author, :status, :tracker, :project ], :conditions => search_filter_clause, :limit => @issue_pages.items_per_page, :offset => @issue_pages.current.offset @@ -206,7 +210,7 @@ class ProjectsController < ApplicationController search_filter_init_list_issues @issues = Issue.find :all, :order => sort_clause, - :include => [ :author, :status, :tracker ], + :include => [ :author, :status, :tracker, :project ], :conditions => search_filter_clause export = StringIO.new diff --git a/redmine/app/controllers/roles_controller.rb b/redmine/app/controllers/roles_controller.rb index 6e4fc74e0..657f62e05 100644 --- a/redmine/app/controllers/roles_controller.rb +++ b/redmine/app/controllers/roles_controller.rb @@ -62,9 +62,6 @@ class RolesController < ApplicationController end def workflow - @roles = Role.find_all - @trackers = Tracker.find_all - @statuses = IssueStatus.find_all @role = Role.find_by_id(params[:role_id]) @tracker = Tracker.find_by_id(params[:tracker_id]) @@ -80,5 +77,8 @@ class RolesController < ApplicationController flash[:notice] = 'Workflow was successfully updated.' end end + @roles = Role.find_all + @trackers = Tracker.find_all + @statuses = IssueStatus.find(:all, :include => :workflows) end end diff --git a/redmine/app/controllers/users_controller.rb b/redmine/app/controllers/users_controller.rb index 64c9fd311..3a6042718 100644 --- a/redmine/app/controllers/users_controller.rb +++ b/redmine/app/controllers/users_controller.rb @@ -16,58 +16,62 @@ # 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 - - def index - list - render :action => 'list' - end + layout 'base' + before_filter :require_admin + + helper :sort + include SortHelper - def list - sort_init 'users.login', 'asc' - sort_update - @user_count = User.count - @user_pages = Paginator.new self, @user_count, + def index + list + render :action => 'list' + 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, + @users = User.find :all,:order => sort_clause, :limit => @user_pages.items_per_page, :offset => @user_pages.current.offset - end + end - def add - if request.get? - @user = User.new - else - @user = User.new(params[:user]) - @user.admin = params[:user][:admin] - if @user.save - flash[:notice] = 'User was successfully created.' - redirect_to :action => 'list' - end - end - end + def add + if request.get? + @user = User.new + 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] + if @user.save + flash[:notice] = 'User was successfully created.' + redirect_to :action => 'list' + end + end + end - def edit - @user = User.find(params[:id]) - if request.post? - @user.admin = params[:user][:admin] if params[:user][:admin] - if @user.update_attributes(params[:user]) - flash[:notice] = 'User was successfully updated.' - redirect_to :action => 'list' - end - end - end + def edit + @user = User.find(params[:id]) + if request.post? + @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? + if @user.update_attributes(params[:user]) + flash[:notice] = 'User was successfully updated.' + redirect_to :action => 'list' + end + end + end - def destroy - User.find(params[:id]).destroy - redirect_to :action => 'list' + def destroy + User.find(params[:id]).destroy + redirect_to :action => 'list' rescue flash[:notice] = "Unable to delete user" redirect_to :action => 'list' - end + end end diff --git a/redmine/app/controllers/versions_controller.rb b/redmine/app/controllers/versions_controller.rb index c4fd241a8..c462867c8 100644 --- a/redmine/app/controllers/versions_controller.rb +++ b/redmine/app/controllers/versions_controller.rb @@ -38,6 +38,9 @@ class VersionsController < ApplicationController @attachment = @version.attachments.find(params[:attachment_id]) @attachment.increment_download send_file @attachment.diskfile, :filename => @attachment.filename + rescue + flash[:notice]="Requested file doesn't exist or has been deleted." + redirect_to :controller => 'projects', :action => 'list_files', :id => @project end def destroy_file diff --git a/redmine/app/helpers/application_helper.rb b/redmine/app/helpers/application_helper.rb index 4a50b949a..de53f2ad6 100644 --- a/redmine/app/helpers/application_helper.rb +++ b/redmine/app/helpers/application_helper.rb @@ -27,7 +27,7 @@ module ApplicationHelper def authorize_for(controller, action) # check if action is allowed on public projects - if @project.public? and Permission.allowed_to_public "%s/%s" % [ controller, action ] + if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ] return true end # check if user is authorized diff --git a/redmine/app/helpers/search_filter_helper.rb b/redmine/app/helpers/search_filter_helper.rb index 7acc8b284..0999dfbcc 100644 --- a/redmine/app/helpers/search_filter_helper.rb +++ b/redmine/app/helpers/search_filter_helper.rb @@ -18,68 +18,73 @@ module SearchFilterHelper def search_filter_criteria(name, options = {}) - session[:search_filter] ||= {} - session[:search_filter][name] ||= {} - unless session[:search_filter][name][:options] and session[:search_filter][name][:conditions] - session[:search_filter][name][:options] = [] - session[:search_filter][name][:conditions] = {} - yield.each { |c| - session[:search_filter][name][:options] << [c[0], c[1].to_s] - session[:search_filter][name][:conditions].store(c[1].to_s, c[2]) - } - end + @search_filter ||= {} + @search_filter[name] ||= {} + @search_filter[name][:options] = [] + @search_filter[name][:conditions] = {} + yield.each { |c| + @search_filter[name][:options] << [c[0], c[1].to_s] + @search_filter[name][:conditions].store(c[1].to_s, c[2]) + } end def search_filter_update - session[:search_filter].each_key {|field| session[:search_filter][field][:value] = params[field] } + @search_filter.each_key {|field| session[:search_filter][field] = params[field] } end def search_filter_clause - clause = ["issues.project_id=?", @project.id] - session[:search_filter].each { |k, v| - v[:value] ||= v[:options][0][1] - if (!v[:conditions][v[:value]][0].empty?) - clause[0] = clause[0] + " AND " + v[:conditions][v[:value]][0] - clause << v[:conditions][v[:value]][1] if !v[:conditions][v[:value]][1].nil? + clause = ["1=1"] + @search_filter.each { |k, v| + filter_value = session[:search_filter][k] || v[:options][0][1] + if v[:conditions][filter_value] + clause[0] = clause[0] + " AND " + v[:conditions][filter_value].first + clause += v[:conditions][filter_value][1..-1] end } clause end - def search_filter_tag(criteria) + def search_filter_tag(criteria, options = {}) + options[:name] = criteria content_tag("select", - options_for_select(session[:search_filter][criteria][:options], session[:search_filter][criteria][:value]), - :name => criteria + options_for_select(@search_filter[criteria][:options], session[:search_filter][criteria]), + options ) end def search_filter_init_list_issues search_filter_criteria('status_id') { - [ ["[Open]", "O", ["issue_statuses.is_closed=?", false]], - ["[All]", "A", ["", false]] + [ [_('[Open]'), "O", ["issue_statuses.is_closed=?", false]], + [_('[All]'), "A", nil] ] + IssueStatus.find(:all).collect {|s| [s.name, s.id, ["issues.status_id=?", s.id]] } } search_filter_criteria('tracker_id') { - [ ["[All]", "A", ["", false]] + [ [_('[All]'), "A", nil] ] + Tracker.find(:all).collect {|s| [s.name, s.id, ["issues.tracker_id=?", s.id]] } } search_filter_criteria('priority_id') { - [ ["[All]", "A", ["", false]] + [ [_('[All]'), "A", nil] ] + Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect {|s| [s.name, s.id, ["issues.priority_id=?", s.id]] } } search_filter_criteria('category_id') { - [ ["[All]", "A", ["", false]], - ["[None]", "N", ["issues.category_id is null"]] + [ [_('[All]'), "A", nil], + [_('[None]'), "N", ["issues.category_id is null"]] ] + @project.issue_categories.find(:all).collect {|s| [s.name, s.id, ["issues.category_id=?", s.id]] } } search_filter_criteria('assigned_to_id') { - [ ["[All]", "A", ["", false]], - ["[Nobody]", "N", ["issues.assigned_to_id is null"]] - ] + User.find(:all).collect {|s| [s.display_name, s.id, ["issues.assigned_to_id=?", s.id]] } - } + [ [_('[All]'), "A", nil], + [_('[None]'), "N", ["issues.assigned_to_id is null"]] + ] + @project.users.collect {|s| [s.display_name, s.id, ["issues.assigned_to_id=?", s.id]] } + } + + search_filter_criteria('subproject_id') { + [ [_('[None]'), "N", ["issues.project_id=?", @project.id]], + [_('[All]'), "A", ["(issues.project_id=? or projects.parent_id=?)", @project.id, @project.id]] + ] + } end end \ No newline at end of file diff --git a/redmine/app/models/attachment.rb b/redmine/app/models/attachment.rb index bc1ff5d87..1e5bd22b4 100644 --- a/redmine/app/models/attachment.rb +++ b/redmine/app/models/attachment.rb @@ -30,7 +30,7 @@ class Attachment < ActiveRecord::Base self.filename = sanitize_filename(@temp_file.original_filename) self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename self.content_type = @temp_file.content_type - self.size = @temp_file.size + self.filesize = @temp_file.size end end end diff --git a/redmine/app/models/enumeration.rb b/redmine/app/models/enumeration.rb index d93db4445..7f985d2f8 100644 --- a/redmine/app/models/enumeration.rb +++ b/redmine/app/models/enumeration.rb @@ -19,6 +19,7 @@ class Enumeration < ActiveRecord::Base before_destroy :check_integrity validates_presence_of :opt, :name + validates_uniqueness_of :name, :scope => [:opt] OPTIONS = [ ["Issue priorities", "IPRI"], diff --git a/redmine/app/models/issue_category.rb b/redmine/app/models/issue_category.rb index b7d4e2623..74adb8f52 100644 --- a/redmine/app/models/issue_category.rb +++ b/redmine/app/models/issue_category.rb @@ -17,9 +17,10 @@ class IssueCategory < ActiveRecord::Base before_destroy :check_integrity - belongs_to :project - + belongs_to :project + validates_presence_of :name + validates_uniqueness_of :name, :scope => [:project_id] private def check_integrity diff --git a/redmine/app/models/issue_status.rb b/redmine/app/models/issue_status.rb index ff34cb666..ef9862092 100644 --- a/redmine/app/models/issue_status.rb +++ b/redmine/app/models/issue_status.rb @@ -17,24 +17,26 @@ class IssueStatus < ActiveRecord::Base before_destroy :check_integrity - has_many :workflows, :foreign_key => "old_status_id" - - validates_presence_of :name - validates_uniqueness_of :name + has_many :workflows, :foreign_key => "old_status_id" - # Returns the default status for new issues - def self.default - find(:first, :conditions =>["is_default=?", true]) - end - - # Returns an array of all statuses the given role can switch to - def new_statuses_allowed_to(role, tracker) - statuses = [] - for workflow in self.workflows.find(:all, :include => :new_status) - statuses << workflow.new_status if workflow.role_id == role.id and workflow.tracker_id == tracker.id - end unless role.nil? - statuses - end + validates_presence_of :name + validates_uniqueness_of :name + validates_length_of :html_color, :is=>6 + validates_format_of :html_color, :with => /^[a-f0-9]*$/i + + # Returns the default status for new issues + def self.default + find(:first, :conditions =>["is_default=?", true]) + end + + # Returns an array of all statuses the given role can switch to + def new_statuses_allowed_to(role, tracker) + statuses = [] + for workflow in self.workflows + statuses << workflow.new_status if workflow.role_id == role.id and workflow.tracker_id == tracker.id + end unless role.nil? or tracker.nil? + statuses + end def name _ self.attributes['name'] diff --git a/redmine/app/models/permission.rb b/redmine/app/models/permission.rb index f66214119..e05ca0fba 100644 --- a/redmine/app/models/permission.rb +++ b/redmine/app/models/permission.rb @@ -43,7 +43,7 @@ class Permission < ActiveRecord::Base end def self.allowed_to_public(action) - @@cached_perms_for_public ||= find(:all, :conditions => ["public=?", true]).collect {|p| "#{p.controller}/#{p.action}"} + @@cached_perms_for_public ||= find(:all, :conditions => ["is_public=?", true]).collect {|p| "#{p.controller}/#{p.action}"} @@cached_perms_for_public.include? action end diff --git a/redmine/app/models/project.rb b/redmine/app/models/project.rb index 7c50ee8cb..e5b5779cb 100644 --- a/redmine/app/models/project.rb +++ b/redmine/app/models/project.rb @@ -16,29 +16,33 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Project < ActiveRecord::Base - has_many :versions, :dependent => true, :order => "versions.date DESC" + has_many :versions, :dependent => true, :order => "versions.effective_date DESC" has_many :members, :dependent => true + has_many :users, :through => :members has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => :status has_many :documents, :dependent => true - has_many :news, :dependent => true, :order => "news.created_on DESC", :include => :author + has_many :news, :dependent => true, :include => :author has_many :issue_categories, :dependent => true has_and_belongs_to_many :custom_fields + acts_as_tree :order => "name", :counter_cache => true validates_presence_of :name, :descr + validates_uniqueness_of :name # returns 5 last created projects def self.latest find(:all, :limit => 5, :order => "created_on DESC") end - # Returns current version of the project - def current_version - versions.find(:first, :conditions => [ "date <= ?", Date.today ], :order => "date DESC, id DESC") - end - # Returns an array of all custom fields enabled for project issues # (explictly associated custom fields and custom fields enabled for all projects) def custom_fields_for_issues (CustomField.for_all + custom_fields).uniq - end + end + +protected + def validate + errors.add(parent_id, " must be a root project") if parent and parent.parent + errors.add_to_base("A project with subprojects can't be a subproject") if parent and projects_count > 0 + end end diff --git a/redmine/app/models/tracker.rb b/redmine/app/models/tracker.rb index 6b123d79c..4283f471d 100644 --- a/redmine/app/models/tracker.rb +++ b/redmine/app/models/tracker.rb @@ -20,6 +20,9 @@ class Tracker < ActiveRecord::Base has_many :issues has_many :workflows, :dependent => true + validates_presence_of :name + validates_uniqueness_of :name + def name _ self.attributes['name'] end diff --git a/redmine/app/models/user.rb b/redmine/app/models/user.rb index 1bc1b5802..e0adbb0df 100644 --- a/redmine/app/models/user.rb +++ b/redmine/app/models/user.rb @@ -18,58 +18,46 @@ require "digest/sha1" class User < ActiveRecord::Base - has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true + has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true - attr_accessor :password - attr_accessor :last_before_login_on - # Prevents unauthorized assignments - attr_protected :admin + attr_accessor :password, :password_confirmation + attr_accessor :last_before_login_on + # Prevents unauthorized assignments + attr_protected :login, :admin, :password, :password_confirmation, :hashed_password - validates_presence_of :login, :firstname, :lastname, :mail - validates_uniqueness_of :login, :mail - - # Login must contain lettres, numbers, underscores only - validates_format_of :login, :with => /^[a-z0-9_]+$/i - validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i - - def before_create - self.hashed_password = User.hash_password(self.password) - end - - def after_create - @password = nil - end + validates_presence_of :login, :firstname, :lastname, :mail + validates_uniqueness_of :login, :mail + # Login must contain lettres, numbers, underscores only + validates_format_of :login, :with => /^[a-z0-9_]+$/i + validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i + # Password length between 4 and 12 + validates_length_of :password, :in => 4..12, :allow_nil => true + validates_confirmation_of :password, :allow_nil => true - # Returns the user that matches user's login and password - def try_to_login - @user = User.login(self.login, self.password) - unless @user.nil? - @user.last_before_login_on = @user.last_login_on - @user.update_attribute(:last_login_on, DateTime.now) - end - @user - end + def before_save + # update hashed_password if password was set + self.hashed_password = User.hash_password(self.password) if self.password + end - # Return user's full name for display - def display_name - firstname + " " + lastname #+ (self.admin ? " (Admin)" : "" ) - end + # Returns the user that matches provided login and password, or nil + def self.try_to_login(login, password) + user = find(:first, :conditions => ["login=? and hashed_password=? and locked=?", login, User.hash_password(password), false]) + if user + user.last_before_login_on = user.last_login_on + user.update_attribute(:last_login_on, Time.now) + end + user + end + + # Return user's full name for display + def display_name + firstname + " " + lastname + end + + def check_password?(clear_password) + User.hash_password(clear_password) == self.hashed_password + end - # Returns the user that matches the given login and password - def self.login(login, password) - hashed_password = hash_password(password || "") - find(:first, - :conditions => ["login = ? and hashed_password = ? and locked = ?", login, hashed_password, false]) - end - - def check_password?(clear_password) - User.hash_password(clear_password) == self.hashed_password - end - - def change_password(current_password, new_password) - self.hashed_password = User.hash_password(new_password) - save - end def role_for_project(project_id) @role_for_projects ||= @@ -82,8 +70,8 @@ class User < ActiveRecord::Base end private - # Return password digest - def self.hash_password(clear_password) - Digest::SHA1.hexdigest(clear_password) - end + # Return password digest + def self.hash_password(clear_password) + Digest::SHA1.hexdigest(clear_password || "") + end end diff --git a/redmine/app/models/version.rb b/redmine/app/models/version.rb index 02dee15c8..70bd6e1c3 100644 --- a/redmine/app/models/version.rb +++ b/redmine/app/models/version.rb @@ -16,12 +16,13 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Version < ActiveRecord::Base - before_destroy :check_integrity - belongs_to :project - has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id' + before_destroy :check_integrity + belongs_to :project + has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id' has_many :attachments, :as => :container, :dependent => true - - validates_presence_of :name, :descr + + validates_presence_of :name + validates_uniqueness_of :name, :scope => [:project_id] private def check_integrity diff --git a/redmine/app/models/workflow.rb b/redmine/app/models/workflow.rb index 212e33350..22c873fc7 100644 --- a/redmine/app/models/workflow.rb +++ b/redmine/app/models/workflow.rb @@ -16,10 +16,9 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Workflow < ActiveRecord::Base + belongs_to :role + belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id' + belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id' - belongs_to :role - belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id' - belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id' - - validates_presence_of :role, :old_status, :new_status + validates_presence_of :role, :old_status, :new_status end diff --git a/redmine/app/views/account/login.rhtml b/redmine/app/views/account/login.rhtml index cc360ebac..bc2b5a562 100644 --- a/redmine/app/views/account/login.rhtml +++ b/redmine/app/views/account/login.rhtml @@ -1,12 +1,12 @@
-
+<%= text_field_tag 'login', nil, :size => 25 %>
-
<%=_('Login')%>: <%= @user.login %>
<%=_('Created on')%>: <%= format_time(@user.created_on) %>,
<%=_('Last update')%>: <%= format_time(@user.updated_on) %>
@@ -39,14 +40,14 @@
<%= start_form_tag :action => 'change_password' %>
-
- <%= password_field_tag 'old_password' %>
+ <%= password_field_tag 'password', nil, :size => 25 %>
- <%= password_field_tag 'new_password' %>
- <%= password_field_tag 'new_password_confirmation' %>
<%=_('Version')%>: <%= RDM_APP_NAME %> <%= RDM_APP_VERSION %>
+ +Environment: +<%=_('Description')%> | -<%=_('Public')%> | - <%= sort_header_tag('projects.created_on', :caption => _('Created on')) %> +<%=_('Public')%> | +<%=_('Subprojects')%> | + <%= sort_header_tag('created_on', :caption => _('Created on')) %>|||
---|---|---|---|---|---|---|
<%= link_to project.name, :controller => 'projects', :action => 'settings', :id => project %> | <%= project.descr %> - | <%= image_tag 'true' if project.public? %> + | <%= image_tag 'true' if project.is_public? %> + | <%= project.projects_count %> | <%= format_date(project.created_on) %> | <%= start_form_tag({:controller => 'projects', :action => 'destroy', :id => project}) %> @@ -26,10 +26,7 @@ <% end %> |
<%= pagination_links_full @project_pages %> +[ <%= @project_pages.current.first_item %> - <%= @project_pages.current.last_item %> / <%= @project_count %> ]
+ +<%= link_to ('» ' + _('New project')), :controller => 'projects', :action => 'add' %>
\ No newline at end of file diff --git a/redmine/app/views/custom_fields/list.rhtml b/redmine/app/views/custom_fields/list.rhtml index 0e29a5b37..2e654072f 100644 --- a/redmine/app/views/custom_fields/list.rhtml +++ b/redmine/app/views/custom_fields/list.rhtml @@ -10,7 +10,7 @@
+
*
<%= text_field 'issue_status', 'name' %>
<%= check_box 'issue_status', 'is_closed' %> @@ -11,7 +11,7 @@
-#<%= text_field 'issue_status', 'html_color', :size => 6 %>
+#<%= text_field 'issue_status', 'html_color', :maxlength => 6 %> * diff --git a/redmine/app/views/issue_statuses/list.rhtml b/redmine/app/views/issue_statuses/list.rhtml index 050e08f0f..8c0532263 100644 --- a/redmine/app/views/issue_statuses/list.rhtml +++ b/redmine/app/views/issue_statuses/list.rhtml @@ -10,10 +10,10 @@ <% for status in @issue_statuses %> -<%=_('Assigned to')%>: <%= @issue.assigned_to.display_name unless @issue.assigned_to.nil? %>
<%=_('Subject')%>: <%= @issue.subject %>
-<%=_('Description')%>: <%= @issue.descr %>
+<%=_('Description')%>: <%= simple_format auto_link @issue.descr %>
<%=_('Created on')%>: <%= format_date(@issue.created_on) %>
<% if authorize_for('issues', 'edit') %> @@ -65,7 +65,7 @@<%= link_to attachment.filename, :action => 'download', :id => @issue, :attachment_id => attachment %> (<%= human_size(attachment.size) %>) | +<%= link_to attachment.filename, :action => 'download', :id => @issue, :attachment_id => attachment %> (<%= human_size(attachment.filesize) %>) | <%= format_date(attachment.created_on) %> | <%= attachment.author.display_name %> | <% if authorize_for('issues', 'destroy_attachment') %> diff --git a/redmine/app/views/layouts/base.rhtml b/redmine/app/views/layouts/base.rhtml index 731632fa4..21bb036d3 100644 --- a/redmine/app/views/layouts/base.rhtml +++ b/redmine/app/views/layouts/base.rhtml @@ -81,7 +81,7 @@ diff --git a/redmine/app/views/news/show.rhtml b/redmine/app/views/news/show.rhtml index 30aa2cda9..d6773cda9 100644 --- a/redmine/app/views/news/show.rhtml +++ b/redmine/app/views/news/show.rhtml @@ -6,5 +6,5 @@ <%=_('Date')%>: <%= format_time(@news.created_on) %> -<%= @news.descr %> +<%= simple_format auto_link @news.descr %> diff --git a/redmine/app/views/projects/_form.rhtml b/redmine/app/views/projects/_form.rhtml index 2d38117a4..89f58354e 100644 --- a/redmine/app/views/projects/_form.rhtml +++ b/redmine/app/views/projects/_form.rhtml @@ -4,15 +4,23 @@