From 310a0f924aa0092228a173cc71864af4ce574f1f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 29 Jul 2006 09:32:58 +0000 Subject: 0.3 unstable git-svn-id: http://redmine.rubyforge.org/svn/trunk@12 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- redmine/app/controllers/account_controller.rb | 141 ++++++++++--- redmine/app/controllers/application.rb | 63 +++--- redmine/app/controllers/auth_sources_controller.rb | 82 ++++++++ .../app/controllers/custom_fields_controller.rb | 57 ++--- redmine/app/controllers/documents_controller.rb | 2 +- redmine/app/controllers/issues_controller.rb | 44 ++-- redmine/app/controllers/projects_controller.rb | 230 +++++++++++---------- redmine/app/controllers/users_controller.rb | 15 +- redmine/app/controllers/welcome_controller.rb | 9 +- redmine/app/helpers/application_helper.rb | 78 ++++--- redmine/app/helpers/auth_sources_helper.rb | 19 ++ redmine/app/helpers/custom_fields_helper.rb | 62 ++++-- redmine/app/models/attachment.rb | 2 +- redmine/app/models/auth_source.rb | 47 +++++ redmine/app/models/auth_source_ldap.rb | 79 +++++++ redmine/app/models/custom_field.rb | 38 ++-- redmine/app/models/custom_value.rb | 42 ++-- redmine/app/models/document.rb | 2 +- redmine/app/models/issue.rb | 12 +- redmine/app/models/issue_custom_field.rb | 27 +++ redmine/app/models/mailer.rb | 46 +++-- redmine/app/models/news.rb | 2 +- redmine/app/models/permission.rb | 2 +- redmine/app/models/project.rb | 52 ++--- redmine/app/models/project_custom_field.rb | 22 ++ redmine/app/models/token.rb | 44 ++++ redmine/app/models/tracker.rb | 3 +- redmine/app/models/user.rb | 49 ++++- redmine/app/models/user_custom_field.rb | 23 +++ redmine/app/views/account/login.rhtml | 34 ++- redmine/app/views/account/lost_password.rhtml | 14 ++ redmine/app/views/account/my_account.rhtml | 36 ++-- redmine/app/views/account/my_page.rhtml | 17 +- redmine/app/views/account/password_recovery.rhtml | 21 ++ redmine/app/views/account/register.rhtml | 46 +++++ redmine/app/views/account/show.rhtml | 8 +- redmine/app/views/admin/index.rhtml | 31 +-- redmine/app/views/admin/info.rhtml | 4 +- redmine/app/views/admin/mail_options.rhtml | 12 +- redmine/app/views/admin/projects.rhtml | 18 +- redmine/app/views/auth_sources/_form.rhtml | 49 +++++ redmine/app/views/auth_sources/edit.rhtml | 7 + redmine/app/views/auth_sources/list.rhtml | 32 +++ redmine/app/views/auth_sources/new.rhtml | 6 + redmine/app/views/custom_fields/_form.rhtml | 55 +++-- redmine/app/views/custom_fields/edit.rhtml | 6 +- redmine/app/views/custom_fields/list.rhtml | 29 +-- redmine/app/views/custom_fields/new.rhtml | 7 +- redmine/app/views/documents/_form.rhtml | 10 +- redmine/app/views/documents/show.rhtml | 2 +- redmine/app/views/issues/change_status.rhtml | 5 +- redmine/app/views/issues/edit.rhtml | 27 +-- redmine/app/views/issues/show.rhtml | 11 +- redmine/app/views/layouts/base.rhtml | 97 ++++++--- redmine/app/views/mailer/_issue.rhtml | 4 +- redmine/app/views/mailer/issue_add.rhtml | 3 - redmine/app/views/mailer/issue_add_en.rhtml | 3 + redmine/app/views/mailer/issue_add_fr.rhtml | 3 + redmine/app/views/mailer/issue_change_status.rhtml | 3 - .../app/views/mailer/issue_change_status_en.rhtml | 3 + .../app/views/mailer/issue_change_status_fr.rhtml | 3 + redmine/app/views/mailer/lost_password_en.rhtml | 3 + redmine/app/views/mailer/lost_password_fr.rhtml | 3 + redmine/app/views/mailer/register_en.rhtml | 3 + redmine/app/views/mailer/register_fr.rhtml | 3 + redmine/app/views/news/_form.rhtml | 8 +- redmine/app/views/news/show.rhtml | 4 +- redmine/app/views/projects/_form.rhtml | 17 +- redmine/app/views/projects/add.rhtml | 1 - redmine/app/views/projects/add_document.rhtml | 4 +- redmine/app/views/projects/add_issue.rhtml | 33 +-- redmine/app/views/projects/changelog.rhtml | 2 +- redmine/app/views/projects/list.rhtml | 2 +- redmine/app/views/projects/list_documents.rhtml | 2 +- redmine/app/views/projects/list_issues.rhtml | 8 +- redmine/app/views/projects/list_news.rhtml | 2 +- redmine/app/views/projects/settings.rhtml | 6 +- redmine/app/views/projects/show.rhtml | 21 +- redmine/app/views/roles/_form.rhtml | 5 +- redmine/app/views/trackers/_form.rhtml | 2 +- redmine/app/views/users/_form.rhtml | 24 ++- redmine/app/views/users/list.rhtml | 6 +- redmine/app/views/versions/_form.rhtml | 4 +- redmine/app/views/welcome/index.rhtml | 9 +- 84 files changed, 1477 insertions(+), 595 deletions(-) create mode 100644 redmine/app/controllers/auth_sources_controller.rb create mode 100644 redmine/app/helpers/auth_sources_helper.rb create mode 100644 redmine/app/models/auth_source.rb create mode 100644 redmine/app/models/auth_source_ldap.rb create mode 100644 redmine/app/models/issue_custom_field.rb create mode 100644 redmine/app/models/project_custom_field.rb create mode 100644 redmine/app/models/token.rb create mode 100644 redmine/app/models/user_custom_field.rb create mode 100644 redmine/app/views/account/lost_password.rhtml create mode 100644 redmine/app/views/account/password_recovery.rhtml create mode 100644 redmine/app/views/account/register.rhtml create mode 100644 redmine/app/views/auth_sources/_form.rhtml create mode 100644 redmine/app/views/auth_sources/edit.rhtml create mode 100644 redmine/app/views/auth_sources/list.rhtml create mode 100644 redmine/app/views/auth_sources/new.rhtml delete mode 100644 redmine/app/views/mailer/issue_add.rhtml create mode 100644 redmine/app/views/mailer/issue_add_en.rhtml create mode 100644 redmine/app/views/mailer/issue_add_fr.rhtml delete mode 100644 redmine/app/views/mailer/issue_change_status.rhtml create mode 100644 redmine/app/views/mailer/issue_change_status_en.rhtml create mode 100644 redmine/app/views/mailer/issue_change_status_fr.rhtml create mode 100644 redmine/app/views/mailer/lost_password_en.rhtml create mode 100644 redmine/app/views/mailer/lost_password_fr.rhtml create mode 100644 redmine/app/views/mailer/register_en.rhtml create mode 100644 redmine/app/views/mailer/register_fr.rhtml (limited to 'redmine/app') diff --git a/redmine/app/controllers/account_controller.rb b/redmine/app/controllers/account_controller.rb index 54e0ef704..b156bfd5b 100644 --- a/redmine/app/controllers/account_controller.rb +++ b/redmine/app/controllers/account_controller.rb @@ -17,11 +17,14 @@ 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 - before_filter :require_login, :except => [:show, :login] + 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]) end @@ -29,49 +32,123 @@ class AccountController < ApplicationController # Login request and validation def login if request.get? - session[:user] = nil + # Logout user + self.logged_in_user = nil else - logged_in_user = User.try_to_login(params[:login], params[:password]) - if logged_in_user - session[:user] = logged_in_user + # Authenticate user + user = User.try_to_login(params[:login], params[:password]) + if user + self.logged_in_user = user redirect_back_or_default :controller => 'account', :action => 'my_page' else - flash[:notice] = _('Invalid user/password') + flash[:notice] = l(:notice_account_invalid_creditentials) end end end - - # Log out current user and redirect to welcome page - def logout - session[:user] = nil - redirect_to(:controller => '') - end - def my_page - @user = session[:user] - @reported_issues = Issue.find(:all, :conditions => ["author_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC') - @assigned_issues = Issue.find(:all, :conditions => ["assigned_to_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC') - end - - # Edit current user's account - def my_account - @user = User.find(session[:user].id) - if request.post? and @user.update_attributes(@params[:user]) - flash[:notice] = 'Account was successfully updated.' - session[:user] = @user + # Log out current user and redirect to welcome page + def logout + self.logged_in_user = nil + redirect_to :controller => '' + end + + # Show logged in user's page + def my_page + @user = self.logged_in_user + @reported_issues = Issue.find(:all, :conditions => ["author_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC') + @assigned_issues = Issue.find(:all, :conditions => ["assigned_to_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC') + end + + # Edit logged in user's account + def my_account + @user = self.logged_in_user + if request.post? and @user.update_attributes(@params[:user]) set_localization - end - end + flash[:notice] = l(:notice_account_updated) + self.logged_in_user.reload + end + end - # Change current user's password + # Change logged in user's password def change_password - @user = User.find(session[:user].id) + @user = self.logged_in_user 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 + flash[:notice] = l(:notice_account_password_updated) if @user.save else - flash[:notice] = 'Wrong password' + flash[:notice] = l(:notice_account_wrong_password) end render :action => 'my_account' - end + 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]) + flash[:notice] = l(:notice_account_unknown_email) and return unless user + token = Token.new(:user => user, :action => "recovery") + if token.save + Mailer.set_language_if_valid(Localization.lang) + 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(Localization.lang) + Mailer.deliver_register(token) + flash[:notice] = l(:notice_account_register_done) + redirect_to :controller => '' + end + end + end + end end diff --git a/redmine/app/controllers/application.rb b/redmine/app/controllers/application.rb index 9cc37cfa9..adae23550 100644 --- a/redmine/app/controllers/application.rb +++ b/redmine/app/controllers/application.rb @@ -18,43 +18,59 @@ 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 + require_login if $RDM_LOGIN_REQUIRED end def set_localization Localization.lang = begin - if session[:user] - session[:user].language + if self.logged_in_user and Localization.langs.keys.include? self.logged_in_user.language + self.logged_in_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 + if Localization.langs.keys.include? accept_lang accept_lang end end rescue nil - end || RDM_DEFAULT_LANG + end || $RDM_DEFAULT_LANG + + set_language_if_valid(Localization.lang) + end def require_login - unless session[:user] + unless self.logged_in_user store_location redirect_to(:controller => "account", :action => "login") + return false end + true 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 + return unless require_login + unless self.logged_in_user.admin? + flash[:notice] = "Acces denied" + redirect_to:controller => '' + return false end + true end # authorizes the user for the requested action. @@ -62,19 +78,18 @@ class ApplicationController < ActionController::Base # 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 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) ) + 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 flash[:notice] = "Acces denied" - redirect_to(:controller => "") + redirect_to :controller => '' false end diff --git a/redmine/app/controllers/auth_sources_controller.rb b/redmine/app/controllers/auth_sources_controller.rb new file mode 100644 index 000000000..fe8536f99 --- /dev/null +++ b/redmine/app/controllers/auth_sources_controller.rb @@ -0,0 +1,82 @@ +# 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' + 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 + 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/redmine/app/controllers/custom_fields_controller.rb b/redmine/app/controllers/custom_fields_controller.rb index 93f6353fa..57430743d 100644 --- a/redmine/app/controllers/custom_fields_controller.rb +++ b/redmine/app/controllers/custom_fields_controller.rb @@ -16,37 +16,48 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class CustomFieldsController < ApplicationController - layout 'base' - before_filter :require_admin - + layout 'base' + before_filter :require_admin + def index list render :action => 'list' end def list - @custom_field_pages, @custom_fields = paginate :custom_fields, :per_page => 10 + @custom_field_pages, @custom_fields = paginate :custom_fields, :per_page => 15 end - + def new - if request.get? - @custom_field = CustomField.new - else - @custom_field = CustomField.new(params[:custom_field]) - if @custom_field.save - flash[:notice] = 'CustomField was successfully created.' - redirect_to :action => 'list' + 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 + 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 - end - end - - def edit - @custom_field = CustomField.find(params[:id]) - if request.post? and @custom_field.update_attributes(params[:custom_field]) - flash[:notice] = 'CustomField was successfully updated.' - redirect_to :action => 'list' - end - end + flash[:notice] = 'Custom field was successfully updated.' + redirect_to :action => 'list' + end + @trackers = Tracker.find(:all) + end def destroy CustomField.find(params[:id]).destroy @@ -54,5 +65,5 @@ class CustomFieldsController < ApplicationController rescue flash[:notice] = "Unable to delete custom field" redirect_to :action => 'list' - end + end end diff --git a/redmine/app/controllers/documents_controller.rb b/redmine/app/controllers/documents_controller.rb index 3c76465c9..cc30f8e1e 100644 --- a/redmine/app/controllers/documents_controller.rb +++ b/redmine/app/controllers/documents_controller.rb @@ -45,7 +45,7 @@ class DocumentsController < ApplicationController # Save the attachment if params[:attachment][:file].size > 0 @attachment = @document.attachments.build(params[:attachment]) - @attachment.author_id = session[:user].id unless session[:user].nil? + @attachment.author_id = self.logged_in_user.id if self.logged_in_user @attachment.save end render :action => 'show' diff --git a/redmine/app/controllers/issues_controller.rb b/redmine/app/controllers/issues_controller.rb index 5d5872f39..fa97e7c1c 100644 --- a/redmine/app/controllers/issues_controller.rb +++ b/redmine/app/controllers/issues_controller.rb @@ -23,21 +23,21 @@ class IssuesController < ApplicationController include CustomFieldsHelper def show - @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", session[:user].role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if session[:user] + @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 + @custom_values = @issue.custom_values.find(:all, :include => :custom_field) end - def edit - @trackers = Tracker.find(:all) + def edit @priorities = Enumeration::get_values('IPRI') if request.get? - @custom_values = @project.custom_fields_for_issues.collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) } + @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 # Retrieve custom fields and values - @custom_values = @project.custom_fields_for_issues.collect { |x| CustomValue.new(:custom_field => x, :value => params["custom_fields"][x.id.to_s]) } - + @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 - if @issue.update_attributes(params[:issue]) + @issue.attributes = params[:issue] + if @issue.save flash[:notice] = 'Issue was successfully updated.' redirect_to :action => 'show', :id => @issue end @@ -46,12 +46,11 @@ class IssuesController < ApplicationController def change_status @history = @issue.histories.build(params[:history]) - @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", session[:user].role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if session[:user] + @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 if params[:confirm] - unless session[:user].nil? - @history.author = session[:user] - end + @history.author_id = self.logged_in_user.id if self.logged_in_user + if @history.save @issue.status = @history.status @issue.fixed_version_id = (params[:issue][:fixed_version_id]) @@ -76,7 +75,7 @@ class IssuesController < ApplicationController # Save the attachment if params[:attachment][:file].size > 0 @attachment = @issue.attachments.build(params[:attachment]) - @attachment.author_id = session[:user].id unless session[:user].nil? + @attachment.author_id = self.logged_in_user.id if self.logged_in_user @attachment.save end redirect_to :action => 'show', :id => @issue @@ -86,17 +85,16 @@ class IssuesController < ApplicationController @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 - end - + + # Send the file in stream mode + def download + @attachment = @issue.attachments.find(params[:attachment_id]) + send_file @attachment.diskfile, :filename => @attachment.filename + end + private - def find_project + def find_project @issue = Issue.find(params[:id]) - @project = @issue.project - end - + @project = @issue.project + end end diff --git a/redmine/app/controllers/projects_controller.rb b/redmine/app/controllers/projects_controller.rb index 2bef221b1..3c4d806b5 100644 --- a/redmine/app/controllers/projects_controller.rb +++ b/redmine/app/controllers/projects_controller.rb @@ -48,11 +48,15 @@ class ProjectsController < ApplicationController # Add a new project def add - @custom_fields = CustomField::find_all - @root_projects = Project::find(:all, :conditions => "parent_id is null") + @custom_fields = IssueCustomField.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 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] = 'Project was successfully created.' redirect_to :controller => 'admin', :action => 'projects' @@ -60,26 +64,33 @@ class ProjectsController < ApplicationController end end - # Show @project + # 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") + @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 = CustomField::find_all + @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 = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids] + @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] = 'Project was successfully updated.' redirect_to :action => 'settings', :id => @project @@ -89,102 +100,101 @@ class ProjectsController < ApplicationController end end end - - # Delete @project - def destroy + + # Delete @project + def destroy if request.post? and params[:confirm] @project.destroy redirect_to :controller => 'admin', :action => 'projects' end - 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 - redirect_to :action => 'settings', :id => @project - else + # 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 + redirect_to :action => 'settings', :id => @project + else settings render :action => 'settings' - end - end - end + end + end + end - # Add a new version to @project - def add_version - @version = @project.versions.build(params[:version]) - if request.post? and @version.save + # Add a new version to @project + def add_version + @version = @project.versions.build(params[:version]) + if request.post? and @version.save redirect_to :action => 'settings', :id => @project - end - end + end + end - # Add a new member to @project - def add_member + # Add a new member to @project + def add_member @member = @project.members.build(params[:member]) - if request.post? - if @member.save + if request.post? + if @member.save flash[:notice] = 'Member was successfully added.' - redirect_to :action => 'settings', :id => @project - else + redirect_to :action => 'settings', :id => @project + else settings render :action => 'settings' end - end - end + end + end - # Show members list of @project - def list_members - @members = @project.members - 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? + # 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 = session[:user].id unless session[:user].nil? - end - if @document.save - redirect_to :action => 'list_documents', :id => @project - end - end - end - - # Show documents list of @project - def list_documents - @documents = @project.documents - end + 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 + 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 - @trackers = Tracker.find(:all) - @priorities = Enumeration::get_values('IPRI') - if request.get? - @issue = @project.issues.build - @custom_values = @project.custom_fields_for_issues.collect { |x| CustomValue.new(:custom_field => x) } - else - # Create the issue and set the author - @issue = @project.issues.build(params[:issue]) - @issue.author = session[:user] unless session[:user].nil? - # Create the document if a file was sent - if params[:attachment][:file].size > 0 - @attachment = @issue.attachments.build(params[:attachment]) - @attachment.author_id = session[:user].id unless session[:user].nil? - end - @custom_values = @project.custom_fields_for_issues.collect { |x| CustomValue.new(:custom_field => x, :value => params["custom_fields"][x.id.to_s]) } - @issue.custom_values = @custom_values - if @issue.save + # 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? + @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 + # Create the document if a file was sent + if params[:attachment][:file].size > 0 + @attachment = @issue.attachments.build(params[:attachment]) + @attachment.author_id = self.logged_in_user.id if self.logged_in_user + end + @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] = "Issue was successfully added." - 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 - + 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' @@ -195,11 +205,11 @@ class ProjectsController < ApplicationController @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, + @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 + :offset => @issue_pages.current.offset end # Export filtered/sorted issues list to CSV @@ -225,29 +235,30 @@ class ProjectsController < ApplicationController :type => 'text/csv; charset=utf-8; header=present', :filename => 'export.csv') end - - # Add a news to @project - def add_news - @news = @project.news.build(params[:news]) - if request.post? - @news.author = session[:user] unless session[:user].nil? - if @news.save - redirect_to :action => 'list_news', :id => @project - end - end - end - # Show news list of @project + # 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 + 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" 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 = session[:user].id unless session[:user].nil? + @attachment.author_id = self.logged_in_user.id if self.logged_in_user if @attachment.save redirect_to :controller => 'projects', :action => 'list_files', :id => @project end @@ -269,14 +280,13 @@ class ProjectsController < ApplicationController 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]) - rescue - flash[:notice] = 'Project not found.' - redirect_to :action => 'list' - end - + # 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]) + rescue + flash[:notice] = 'Project not found.' + redirect_to :action => 'list' + end end diff --git a/redmine/app/controllers/users_controller.rb b/redmine/app/controllers/users_controller.rb index 3a6042718..758afc2d8 100644 --- a/redmine/app/controllers/users_controller.rb +++ b/redmine/app/controllers/users_controller.rb @@ -21,6 +21,8 @@ class UsersController < ApplicationController helper :sort include SortHelper + helper :custom_fields + include CustomFieldsHelper def index list @@ -41,12 +43,15 @@ class UsersController < ApplicationController def add if request.get? - @user = User.new + @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] + @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] = 'User was successfully created.' redirect_to :action => 'list' @@ -56,10 +61,16 @@ class UsersController < ApplicationController def edit @user = User.find(params[:id]) - if request.post? + 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? + 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] = 'User was successfully updated.' redirect_to :action => 'list' diff --git a/redmine/app/controllers/welcome_controller.rb b/redmine/app/controllers/welcome_controller.rb index b266975aa..c47198d51 100644 --- a/redmine/app/controllers/welcome_controller.rb +++ b/redmine/app/controllers/welcome_controller.rb @@ -16,11 +16,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class WelcomeController < ApplicationController - layout 'base' - - def index + layout 'base' + + def index @news = News.latest @projects = Project.latest - end - + end end diff --git a/redmine/app/helpers/application_helper.rb b/redmine/app/helpers/application_helper.rb index de53f2ad6..ddb846073 100644 --- a/redmine/app/helpers/application_helper.rb +++ b/redmine/app/helpers/application_helper.rb @@ -17,35 +17,38 @@ module ApplicationHelper - def loggedin? - session[:user] - end + # return current logged in user or nil + def loggedin? + @logged_in_user + end + + # return true if user is loggend in and is admin, otherwise false + def admin_loggedin? + @logged_in_user and @logged_in_user.admin? + end - def admin_loggedin? - session[:user] && session[:user].admin - end - - def authorize_for(controller, action) + def authorize_for(controller, action) # check if action is allowed on public projects if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ] return true - end + end # check if user is authorized - if session[:user] and (session[:user].admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], session[:user].role_for_project(@project.id) ) ) - return true - end - return false - end - - def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action]) - end - - # Display a link to user's account page - def link_to_user(user) - link_to user.display_name, :controller => 'account', :action => 'show', :id => user - end - + if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project.id) ) ) + return true + end + return false + end + + # Display a link if user is authorized + def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action]) + end + + # Display a link to user's account page + def link_to_user(user) + link_to user.display_name, :controller => 'account', :action => 'show', :id => user + end + def format_date(date) _('(date)', date) if date end @@ -61,5 +64,30 @@ module ApplicationHelper html << ' ' + link_to((_('Next') + ' »'), { :page => paginator.current.next }) if paginator.current.next html end - + + def error_messages_for(object_name, options = {}) + options = options.symbolize_keys + object = instance_variable_get("@#{object_name}") + if object && !object.errors.empty? + # build full_messages here with controller current language + full_messages = [] + object.errors.each do |attr, msg| + next if msg.nil? + if attr == "base" + full_messages << l(msg) + else + full_messages << "« " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " » " + l(msg) + end + end + content_tag("div", + content_tag( + options[:header_tag] || "h2", lwr(:gui_validation_error, object.errors.count) + " :" + ) + + content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }), + "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation" + ) + else + "" + end + end end diff --git a/redmine/app/helpers/auth_sources_helper.rb b/redmine/app/helpers/auth_sources_helper.rb new file mode 100644 index 000000000..d47e9856a --- /dev/null +++ b/redmine/app/helpers/auth_sources_helper.rb @@ -0,0 +1,19 @@ +# 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. + +module AuthSourcesHelper +end diff --git a/redmine/app/helpers/custom_fields_helper.rb b/redmine/app/helpers/custom_fields_helper.rb index 4e3aea50f..10cb1bb94 100644 --- a/redmine/app/helpers/custom_fields_helper.rb +++ b/redmine/app/helpers/custom_fields_helper.rb @@ -16,21 +16,49 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module CustomFieldsHelper - def custom_field_tag(custom_value) - - custom_field = custom_value.custom_field - - field_name = "custom_fields[#{custom_field.id}]" - - case custom_field.typ - when 0 .. 2 - text_field_tag field_name, custom_value.value - when 3 - check_box field_name - when 4 - select_tag field_name, - options_for_select(custom_field.possible_values.split('|'), - custom_value.value) - end - end + + def custom_field_tag(custom_value) + custom_field = custom_value.custom_field + field_name = "custom_fields[#{custom_field.id}]" + case custom_field.field_format + when "string", "int", "date" + text_field_tag field_name, custom_value.value + when "text" + text_area_tag field_name, custom_value.value, :cols => 60, :rows => 3 + when "bool" + check_box_tag(field_name, "1", custom_value.value == "1") + + hidden_field_tag(field_name, "0") + when "list" + select_tag field_name, + "" + options_for_select(custom_field.possible_values.split('|'), + custom_value.value) + end + end + + def custom_field_label_tag(custom_value) + content_tag "label", custom_value.custom_field.name + + (custom_value.custom_field.is_required? ? " *" : "") + end + + def custom_field_tag_with_label(custom_value) + case custom_value.custom_field.field_format + when "bool" + custom_field_tag(custom_value) + " " + custom_field_label_tag(custom_value) + else + custom_field_label_tag(custom_value) + "
" + custom_field_tag(custom_value) + end + end + + def show_value(custom_value) + case custom_value.custom_field.field_format + when "bool" + l_YesNo(custom_value.value == "1") + else + custom_value.value + end + end + + def custom_field_formats_for_select + CustomField::FIELD_FORMATS.keys.collect { |k| [ l(CustomField::FIELD_FORMATS[k]), k ] } + end end diff --git a/redmine/app/models/attachment.rb b/redmine/app/models/attachment.rb index 1e5bd22b4..2e1e9b156 100644 --- a/redmine/app/models/attachment.rb +++ b/redmine/app/models/attachment.rb @@ -55,7 +55,7 @@ class Attachment < ActiveRecord::Base # Returns file's location on disk def diskfile - "#{RDM_STORAGE_PATH}/#{self.disk_filename}" + "#{$RDM_STORAGE_PATH}/#{self.disk_filename}" end def increment_download diff --git a/redmine/app/models/auth_source.rb b/redmine/app/models/auth_source.rb new file mode 100644 index 000000000..47eec106d --- /dev/null +++ b/redmine/app/models/auth_source.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 AuthSource < ActiveRecord::Base + has_many :users + + validates_presence_of :name + validates_uniqueness_of :name + + def authenticate(login, password) + end + + def test_connection + end + + def auth_method_name + "Abstract" + end + + # Try to authenticate a user not yet registered against available sources + def self.authenticate(login, password) + AuthSource.find(:all, :conditions => ["onthefly_register=?", true]).each do |source| + begin + logger.debug "Authenticating '#{login}' against '#{source.name}'" if logger && logger.debug? + attrs = source.authenticate(login, password) + rescue + attrs = nil + end + return attrs if attrs + end + return nil + end +end diff --git a/redmine/app/models/auth_source_ldap.rb b/redmine/app/models/auth_source_ldap.rb new file mode 100644 index 000000000..9579a1094 --- /dev/null +++ b/redmine/app/models/auth_source_ldap.rb @@ -0,0 +1,79 @@ +# 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. + +require 'net/ldap' +require 'iconv' + +class AuthSourceLdap < AuthSource + validates_presence_of :host, :port, :attr_login + + def after_initialize + self.port = 389 if self.port == 0 + end + + def authenticate(login, password) + attrs = [] + # get user's DN + ldap_con = initialize_ldap_con(self.account, self.account_password) + login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) + object_filter = Net::LDAP::Filter.eq( "objectClass", "organizationalPerson" ) + dn = String.new + ldap_con.search( :base => self.base_dn, + :filter => object_filter & login_filter, + :attributes=> ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]) do |entry| + dn = entry.dn + attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname), + :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname), + :mail => AuthSourceLdap.get_attr(entry, self.attr_mail), + :auth_source_id => self.id ] + end + return nil if dn.empty? + logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug? + # authenticate user + ldap_con = initialize_ldap_con(dn, password) + return nil unless ldap_con.bind + # return user's attributes + logger.debug "Authentication successful for '#{login}'" if logger && logger.debug? + attrs + rescue Net::LDAP::LdapError => text + raise "LdapError: " + text + end + + # test the connection to the LDAP + def test_connection + ldap_con = initialize_ldap_con(self.account, self.account_password) + ldap_con.open { } + rescue Net::LDAP::LdapError => text + raise "LdapError: " + text + end + + def auth_method_name + "LDAP" + end + +private + def initialize_ldap_con(ldap_user, ldap_password) + Net::LDAP.new( {:host => self.host, + :port => self.port, + :auth => { :method => :simple, :username => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_user), :password => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_password) }} + ) + end + + def self.get_attr(entry, attr_name) + entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name] + end +end diff --git a/redmine/app/models/custom_field.rb b/redmine/app/models/custom_field.rb index 9e817d1ef..924a874a3 100644 --- a/redmine/app/models/custom_field.rb +++ b/redmine/app/models/custom_field.rb @@ -16,23 +16,27 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class CustomField < ActiveRecord::Base + has_many :custom_values, :dependent => true - has_and_belongs_to_many :projects - has_many :custom_values, :dependent => true - has_many :issues, :through => :issue_custom_values + FIELD_FORMATS = { "list" => :label_list, + "date" => :label_date, + "bool" => :label_boolean, + "int" => :label_integer, + "string" => :label_string, + "text" => :label_text + }.freeze - validates_presence_of :name, :typ - validates_uniqueness_of :name + validates_presence_of :name, :field_format + validates_uniqueness_of :name + validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys + validates_presence_of :possible_values, :if => Proc.new { |field| field.field_format == "list" } - TYPES = [ - [ "Integer", 0 ], - [ "String", 1 ], - [ "Date", 2 ], - [ "Boolean", 3 ], - [ "List", 4 ] - ].freeze - - def self.for_all - find(:all, :conditions => ["is_for_all=?", true]) - end -end + # to move in project_custom_field + def self.for_all + find(:all, :conditions => ["is_for_all=?", true]) + end + + def type_name + nil + end +end diff --git a/redmine/app/models/custom_value.rb b/redmine/app/models/custom_value.rb index faaa8ff82..ac72e5aba 100644 --- a/redmine/app/models/custom_value.rb +++ b/redmine/app/models/custom_value.rb @@ -16,26 +16,28 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class CustomValue < ActiveRecord::Base - belongs_to :issue - belongs_to :custom_field - + belongs_to :custom_field + belongs_to :customized, :polymorphic => true + protected def validate - errors.add(custom_field.name, "can't be blank") if custom_field.is_required? and value.empty? - errors.add(custom_field.name, "is not valid") unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp) - - case custom_field.typ - when 0 - errors.add(custom_field.name, "must be an integer") unless value =~ /^[0-9]*$/ - when 1 - errors.add(custom_field.name, "is too short") if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0 - errors.add(custom_field.name, "is too long") if custom_field.max_length > 0 and value.length > custom_field.max_length - when 2 - errors.add(custom_field.name, "must be a valid date") unless value =~ /^(\d+)\/(\d+)\/(\d+)$/ or value.empty? - when 3 - - when 4 - errors.add(custom_field.name, "is not a valid value") unless custom_field.possible_values.split('|').include? value or value.empty? - end + # errors are added to customized object unless it's nil + object = customized || self + + object.errors.add(custom_field.name, :activerecord_error_blank) if custom_field.is_required? and value.empty? + object.errors.add(custom_field.name, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp) + + object.errors.add(custom_field.name, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0 + object.errors.add(custom_field.name, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length + + case custom_field.field_format + when "int" + object.errors.add(custom_field.name, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/ + when "date" + object.errors.add(custom_field.name, :activerecord_error_invalid) unless value =~ /^(\d+)\/(\d+)\/(\d+)$/ or value.empty? + when "list" + object.errors.add(custom_field.name, :activerecord_error_inclusion) unless custom_field.possible_values.split('|').include? value or value.empty? + end end -end +end + diff --git a/redmine/app/models/document.rb b/redmine/app/models/document.rb index 40c3a1656..08e0ef607 100644 --- a/redmine/app/models/document.rb +++ b/redmine/app/models/document.rb @@ -20,5 +20,5 @@ class Document < ActiveRecord::Base belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id" has_many :attachments, :as => :container, :dependent => true - validates_presence_of :title + validates_presence_of :project, :title, :category end diff --git a/redmine/app/models/issue.rb b/redmine/app/models/issue.rb index 4a21ac03b..dc5b3fd84 100644 --- a/redmine/app/models/issue.rb +++ b/redmine/app/models/issue.rb @@ -29,15 +29,19 @@ class Issue < ActiveRecord::Base has_many :histories, :class_name => 'IssueHistory', :dependent => true, :order => "issue_histories.created_on DESC", :include => :status has_many :attachments, :as => :container, :dependent => true - has_many :custom_values, :dependent => true + has_many :custom_values, :dependent => true, :as => :customized has_many :custom_fields, :through => :custom_values - validates_presence_of :subject, :descr, :priority, :tracker, :author + validates_presence_of :subject, :description, :priority, :tracker, :author + validates_associated :custom_values, :on => :update # set default status for new issues + def before_validation + self.status = IssueStatus.default if new_record? + end + def before_create - self.status = IssueStatus.default - build_history + build_history end def long_id diff --git a/redmine/app/models/issue_custom_field.rb b/redmine/app/models/issue_custom_field.rb new file mode 100644 index 000000000..209ae206b --- /dev/null +++ b/redmine/app/models/issue_custom_field.rb @@ -0,0 +1,27 @@ +# 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 IssueCustomField < CustomField + has_and_belongs_to_many :projects, :join_table => "custom_fields_projects", :foreign_key => "custom_field_id" + has_and_belongs_to_many :trackers, :join_table => "custom_fields_trackers", :foreign_key => "custom_field_id" + has_many :issues, :through => :issue_custom_values + + def type_name + :label_issue_plural + end +end + diff --git a/redmine/app/models/mailer.rb b/redmine/app/models/mailer.rb index b04ec7ebc..bf4c85dbb 100644 --- a/redmine/app/models/mailer.rb +++ b/redmine/app/models/mailer.rb @@ -17,20 +17,34 @@ class Mailer < ActionMailer::Base - def issue_change_status(issue) - # Sends to all project members - @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } - @from = 'redmine@somenet.foo' - @subject = "Issue ##{issue.id} has been updated" - @body['issue'] = issue - end - - def issue_add(issue) - # Sends to all project members - @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } - @from = 'redmine@somenet.foo' - @subject = "Issue ##{issue.id} has been reported" - @body['issue'] = issue - end - + def issue_change_status(issue) + # Sends to all project members + @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } + @from = 'redmine@somenet.foo' + @subject = "Issue ##{issue.id} has been updated" + @body['issue'] = issue + end + + def issue_add(issue) + # Sends to all project members + @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } + @from = 'redmine@somenet.foo' + @subject = "Issue ##{issue.id} has been reported" + @body['issue'] = issue + end + + def lost_password(token) + @recipients = token.user.mail + @from = 'redmine@somenet.foo' + @subject = "redMine password" + @body['token'] = token + end + + def register(token) + @recipients = token.user.mail + @from = 'redmine@somenet.foo' + @subject = "redMine account activation" + @body['token'] = token + end + end diff --git a/redmine/app/models/news.rb b/redmine/app/models/news.rb index 0642a4bf5..c4884ace5 100644 --- a/redmine/app/models/news.rb +++ b/redmine/app/models/news.rb @@ -19,7 +19,7 @@ class News < ActiveRecord::Base belongs_to :project belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' - validates_presence_of :title, :shortdescr, :descr + validates_presence_of :title, :description # returns last created news def self.latest diff --git a/redmine/app/models/permission.rb b/redmine/app/models/permission.rb index e05ca0fba..164ca21b9 100644 --- a/redmine/app/models/permission.rb +++ b/redmine/app/models/permission.rb @@ -18,7 +18,7 @@ class Permission < ActiveRecord::Base has_and_belongs_to_many :roles - validates_presence_of :controller, :action, :descr + validates_presence_of :controller, :action, :description GROUPS = { 100 => "Project", diff --git a/redmine/app/models/project.rb b/redmine/app/models/project.rb index e5b5779cb..ee848cb30 100644 --- a/redmine/app/models/project.rb +++ b/redmine/app/models/project.rb @@ -16,30 +16,34 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Project < ActiveRecord::Base - 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, :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 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 - + has_many :versions, :dependent => true, :order => "versions.effective_date DESC, versions.name DESC" + has_many :members, :dependent => true + has_many :users, :through => :members + has_many :custom_values, :dependent => true, :as => :customized + has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => :status + has_many :documents, :dependent => true + has_many :news, :dependent => true, :include => :author + has_many :issue_categories, :dependent => true, :order => "issue_categories.name" + has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_projects', :association_foreign_key => 'custom_field_id' + acts_as_tree :order => "name", :counter_cache => true + + validates_presence_of :name, :description + validates_uniqueness_of :name + validates_associated :custom_values, :on => :update + + # returns 5 last created projects + def self.latest + find(:all, :limit => 5, :order => "created_on 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(tracker) + tracker.custom_fields.find(:all, :include => :projects, + :conditions => ["is_for_all=? or project_id=?", true, self.id]) + #(CustomField.for_all + custom_fields).uniq + end + protected def validate errors.add(parent_id, " must be a root project") if parent and parent.parent diff --git a/redmine/app/models/project_custom_field.rb b/redmine/app/models/project_custom_field.rb new file mode 100644 index 000000000..baa533812 --- /dev/null +++ b/redmine/app/models/project_custom_field.rb @@ -0,0 +1,22 @@ +# 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 ProjectCustomField < CustomField + def type_name + :label_project_plural + end +end diff --git a/redmine/app/models/token.rb b/redmine/app/models/token.rb new file mode 100644 index 000000000..98745d29e --- /dev/null +++ b/redmine/app/models/token.rb @@ -0,0 +1,44 @@ +# 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 Token < ActiveRecord::Base + belongs_to :user + + @@validity_time = 1.day + + def before_create + self.value = Token.generate_token_value + end + + # Return true if token has expired + def expired? + return Time.now > self.created_on + @@validity_time + end + + # Delete all expired tokens + def self.destroy_expired + Token.delete_all ["created_on < ?", Time.now - @@validity_time] + end + +private + def self.generate_token_value + chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + token_value = '' + 40.times { |i| token_value << chars[rand(chars.size-1)] } + token_value + end +end diff --git a/redmine/app/models/tracker.rb b/redmine/app/models/tracker.rb index 4283f471d..ca37eb939 100644 --- a/redmine/app/models/tracker.rb +++ b/redmine/app/models/tracker.rb @@ -19,7 +19,8 @@ class Tracker < ActiveRecord::Base before_destroy :check_integrity has_many :issues has_many :workflows, :dependent => true - + has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_trackers', :association_foreign_key => 'custom_field_id' + validates_presence_of :name validates_uniqueness_of :name diff --git a/redmine/app/models/user.rb b/redmine/app/models/user.rb index e0adbb0df..ea313483c 100644 --- a/redmine/app/models/user.rb +++ b/redmine/app/models/user.rb @@ -19,7 +19,9 @@ require "digest/sha1" class User < ActiveRecord::Base has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true - + has_many :custom_values, :dependent => true, :as => :customized + belongs_to :auth_source + attr_accessor :password, :password_confirmation attr_accessor :last_before_login_on # Prevents unauthorized assignments @@ -33,6 +35,12 @@ class User < ActiveRecord::Base # Password length between 4 and 12 validates_length_of :password, :in => 4..12, :allow_nil => true validates_confirmation_of :password, :allow_nil => true + validates_associated :custom_values, :on => :update + + # Account statuses + STATUS_ACTIVE = 1 + STATUS_REGISTERED = 2 + STATUS_LOCKED = 3 def before_save # update hashed_password if password was set @@ -41,23 +49,52 @@ class User < ActiveRecord::Base # 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]) + user = find(:first, :conditions => ["login=?", login]) if user - user.last_before_login_on = user.last_login_on - user.update_attribute(:last_login_on, Time.now) - end + # user is already in local database + return nil if !user.active? + if user.auth_source + # user has an external authentication method + return nil unless user.auth_source.authenticate(login, password) + else + # local authentication + return nil unless User.hash_password(password) == user.hashed_password + end + else + # user is not yet registered, try to authenticate with available sources + attrs = AuthSource.authenticate(login, password) + if attrs + onthefly = new(*attrs) + onthefly.login = login + onthefly.language = $RDM_DEFAULT_LANG + if onthefly.save + user = find(:first, :conditions => ["login=?", login]) + end + end + end + user.update_attribute(:last_login_on, Time.now) if user user + + rescue => text + raise text end # Return user's full name for display def display_name firstname + " " + lastname end + + def active? + self.status == STATUS_ACTIVE + end + + def locked? + self.status == STATUS_LOCKED + end def check_password?(clear_password) User.hash_password(clear_password) == self.hashed_password end - def role_for_project(project_id) @role_for_projects ||= diff --git a/redmine/app/models/user_custom_field.rb b/redmine/app/models/user_custom_field.rb new file mode 100644 index 000000000..866234a7f --- /dev/null +++ b/redmine/app/models/user_custom_field.rb @@ -0,0 +1,23 @@ +# 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 UserCustomField < CustomField + def type_name + :label_user_plural + end +end + diff --git a/redmine/app/views/account/login.rhtml b/redmine/app/views/account/login.rhtml index bc2b5a562..2c806b421 100644 --- a/redmine/app/views/account/login.rhtml +++ b/redmine/app/views/account/login.rhtml @@ -1,13 +1,25 @@ -
-

<%=_('Please login') %>

+
+ \ No newline at end of file +

+<%= end_form_tag %> +
+<% unless $RDM_SELF_REGISTRATION == false %><%= link_to l(:label_register), :action => 'register' %> |<% end %> +<%= link_to l(:label_password_lost), :action => 'lost_password' %> +
+ \ No newline at end of file diff --git a/redmine/app/views/account/lost_password.rhtml b/redmine/app/views/account/lost_password.rhtml new file mode 100644 index 000000000..cd392f243 --- /dev/null +++ b/redmine/app/views/account/lost_password.rhtml @@ -0,0 +1,14 @@ +
+ +
\ No newline at end of file diff --git a/redmine/app/views/account/my_account.rhtml b/redmine/app/views/account/my_account.rhtml index 7248f0e4a..097e23181 100644 --- a/redmine/app/views/account/my_account.rhtml +++ b/redmine/app/views/account/my_account.rhtml @@ -1,34 +1,34 @@ -

<%=_('My account')%>

+

<%=l(:label_my_account)%>

-

<%=_('Login')%>: <%= @user.login %>
-<%=_('Created on')%>: <%= format_time(@user.created_on) %>, -<%=_('Last update')%>: <%= format_time(@user.updated_on) %>

+

<%=l(:field_login)%>: <%= @user.login %>
+<%=l(:field_created_on)%>: <%= format_time(@user.created_on) %>, +<%=l(:field_updated_on)%>: <%= format_time(@user.updated_on) %>

<%= error_messages_for 'user' %>
-

<%=_('Information')%>

+

<%=l(:label_information_plural)%>

  <%= start_form_tag :action => 'my_account' %> -


+


<%= text_field 'user', 'firstname' %>

-


+


<%= text_field 'user', 'lastname' %>

-


- <%= text_field 'user', 'mail' %>

+


+ <%= text_field 'user', 'mail' %>

-


- <%= select("user", "language", Localization.langs) %>

+


+ <%= select("user", "language", Localization.langs.invert) %>

-

<%= check_box 'user', 'mail_notification' %>

+

<%= check_box 'user', 'mail_notification' %>

-
<%= submit_tag _('Save') %>
+
<%= submit_tag l(:button_save) %>
<%= end_form_tag %>
@@ -36,20 +36,20 @@
-

<%=_('Password')%>

+

<%=l(:field_password)%>

  <%= start_form_tag :action => 'change_password' %> -


+


<%= password_field_tag 'password', nil, :size => 25 %>

-


+


<%= password_field_tag 'new_password', nil, :size => 25 %>

-


+


<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %>

-
<%= submit_tag _('Save') %>
+
<%= submit_tag l(:button_save) %>
<%= end_form_tag %>
\ No newline at end of file diff --git a/redmine/app/views/account/my_page.rhtml b/redmine/app/views/account/my_page.rhtml index 7f6458262..54b5685e8 100644 --- a/redmine/app/views/account/my_page.rhtml +++ b/redmine/app/views/account/my_page.rhtml @@ -1,19 +1,22 @@ -

<%=_('My page') %>

+

<%=l(:label_my_page)%>

-<%=_('Welcome')%> <%= @user.firstname %>
<% unless @user.last_before_login_on.nil? %> - <%=_('Last login')%>: <%= format_time(@user.last_before_login_on) %> + <%=l(:label_last_login)%>: <%= format_time(@user.last_before_login_on) %> <% end %>

-

<%=_('Reported issues')%>

+

<%=l(:label_reported_issues)%>

<%= render :partial => 'issues/list_simple', :locals => { :issues => @reported_issues } %> - <%= "

(Last #{@reported_issues.length} updated)

" if @reported_issues.length > 0 %> + <% if @reported_issues.length > 0 %> +

<%=lwr(:label_last_updates, @reported_issues.length)%>

+ <% end %>
-

<%=_('Assigned to me')%>

+

<%=l(:label_assigned_to_me_issues)%>

<%= render :partial => 'issues/list_simple', :locals => { :issues => @assigned_issues } %> - <%= "

(Last #{@assigned_issues.length} updated)

" if @assigned_issues.length > 0 %> + <% if @assigned_issues.length > 0 %> +

<%=lwr(:label_last_updates, @assigned_issues.length)%>

+ <% end %>
\ No newline at end of file diff --git a/redmine/app/views/account/password_recovery.rhtml b/redmine/app/views/account/password_recovery.rhtml new file mode 100644 index 000000000..b4f73d28c --- /dev/null +++ b/redmine/app/views/account/password_recovery.rhtml @@ -0,0 +1,21 @@ +
+ +
\ No newline at end of file diff --git a/redmine/app/views/account/register.rhtml b/redmine/app/views/account/register.rhtml new file mode 100644 index 000000000..2bdf380f9 --- /dev/null +++ b/redmine/app/views/account/register.rhtml @@ -0,0 +1,46 @@ +

<%=l(:label_register)%>

+ +<%= start_form_tag %> + +<%= error_messages_for 'user' %> + +
+ +

*
+<%= text_field 'user', 'login', :size => 25 %>

+ +

*
+<%= password_field_tag 'password', nil, :size => 25 %>

+ +

*
+<%= password_field_tag 'password_confirmation', nil, :size => 25 %>

+ +

*
+<%= text_field 'user', 'firstname' %>

+ +

*
+<%= text_field 'user', 'lastname' %>

+ +

*
+<%= text_field 'user', 'mail' %>

+ +


+<%= select("user", "language", Localization.langs.invert) %>

+ +<% for custom_value in @custom_values %> +
+

<%= content_tag "label", custom_value.custom_field.name %> + <% if custom_value.custom_field.is_required? %>*<% end %> +
+ <%= custom_field_tag custom_value %>

+
+<% end %> + +
+ +

<%= check_box 'user', 'mail_notification' %>

+ +
+ + <%= submit_tag l(:button_submit) %> +<%= end_form_tag %> diff --git a/redmine/app/views/account/show.rhtml b/redmine/app/views/account/show.rhtml index df918e5bf..78fe0a679 100644 --- a/redmine/app/views/account/show.rhtml +++ b/redmine/app/views/account/show.rhtml @@ -2,10 +2,10 @@

<%= mail_to @user.mail %>
-<%=_('Registered on')%>: <%= format_date(@user.created_on) %> +<%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %>

-

<%=_('Projects')%>

+

<%=l(:label_project_plural)%>

<% for membership in @user.memberships %> <%= membership.project.name %> (<%= membership.role.name %>, <%= format_date(membership.created_on) %>) @@ -13,7 +13,7 @@ <% end %>

-

<%=_('Activity')%>

+

<%=l(:label_activity)%>

-<%=_('Reported issues')%>: <%= Issue.count( [ "author_id=?", @user.id]) %> +<%=l(:label_reported_issues)%>: <%= Issue.count(["author_id=?", @user.id]) %>

\ No newline at end of file diff --git a/redmine/app/views/admin/index.rhtml b/redmine/app/views/admin/index.rhtml index b3607d813..d937e287c 100644 --- a/redmine/app/views/admin/index.rhtml +++ b/redmine/app/views/admin/index.rhtml @@ -1,45 +1,50 @@ -

<%=_('Administration')%>

+

<%=l(:label_administration)%>

<%= image_tag "projects" %> -<%= link_to _('Projects'), :controller => 'admin', :action => 'projects' %> | -<%= link_to _('New'), :controller => 'projects', :action => 'add' %> +<%= link_to l(:label_project_plural), :controller => 'admin', :action => 'projects' %> | +<%= link_to l(:label_new), :controller => 'projects', :action => 'add' %>

<%= image_tag "users" %> -<%= link_to _('Users'), :controller => 'users' %> | -<%= link_to _('New'), :controller => 'users', :action => 'add' %> +<%= link_to l(:label_user_plural), :controller => 'users' %> | +<%= link_to l(:label_new), :controller => 'users', :action => 'add' %>

<%= image_tag "role" %> -<%= link_to _('Roles and permissions'), :controller => 'roles' %> +<%= link_to l(:label_role_and_permissions), :controller => 'roles' %>

<%= image_tag "tracker" %> -<%= link_to _('Trackers'), :controller => 'trackers' %> | -<%= link_to _('Custom fields'), :controller => 'custom_fields' %> +<%= link_to l(:label_tracker_plural), :controller => 'trackers' %> | +<%= link_to l(:label_custom_field_plural), :controller => 'custom_fields' %>

<%= image_tag "workflow" %> -<%= link_to _('Issue Statuses'), :controller => 'issue_statuses' %> | -<%= link_to _('Workflow'), :controller => 'roles', :action => 'workflow' %> +<%= link_to l(:label_issue_status_plural), :controller => 'issue_statuses' %> | +<%= link_to l(:label_workflow), :controller => 'roles', :action => 'workflow' %>

<%= image_tag "options" %> -<%= link_to _('Enumerations'), :controller => 'enumerations' %> +<%= link_to l(:label_enumerations), :controller => 'enumerations' %>

<%= image_tag "mailer" %> -<%= link_to _('Mail notifications'), :controller => 'admin', :action => 'mail_options' %> +<%= link_to l(:field_mail_notification), :controller => 'admin', :action => 'mail_options' %> +

+ +

+<%= image_tag "login" %> +<%= link_to l(:label_authentication), :controller => 'auth_sources' %>

<%= image_tag "help" %> -<%= link_to _('Information'), :controller => 'admin', :action => 'info' %> +<%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %>

\ No newline at end of file diff --git a/redmine/app/views/admin/info.rhtml b/redmine/app/views/admin/info.rhtml index c987805c9..03dddafb6 100644 --- a/redmine/app/views/admin/info.rhtml +++ b/redmine/app/views/admin/info.rhtml @@ -1,8 +1,8 @@

<%=_('Information')%>

-

<%=_('Version')%>: <%= RDM_APP_NAME %> <%= RDM_APP_VERSION %>

+

<%=l(:field_version)%>: <%= RDM_APP_NAME %> <%= RDM_APP_VERSION %>

-Environment: +<%=l(:label_environment)%>: +
@@ -64,15 +107,14 @@ <% end %> - <% unless session[:user].nil? %> + <% if loggedin? and @logged_in_user.memberships.length > 0 %>

<%=_('My projects') %>

- <% end %> - + <% end %>
@@ -81,7 +123,10 @@
diff --git a/redmine/app/views/mailer/_issue.rhtml b/redmine/app/views/mailer/_issue.rhtml index 1f238f513..f2ab6fa5f 100644 --- a/redmine/app/views/mailer/_issue.rhtml +++ b/redmine/app/views/mailer/_issue.rhtml @@ -1,6 +1,6 @@ <%=_('Issue')%> #<%= issue.id %> - <%= issue.subject %> <%=_('Author')%>: <%= issue.author.display_name %> -<%= issue.descr %> +<%= issue.description %> -http://<%= RDM_HOST_NAME %>/issues/show/<%= issue.id %> \ No newline at end of file +http://<%= $RDM_HOST_NAME %>/issues/show/<%= issue.id %> \ No newline at end of file diff --git a/redmine/app/views/mailer/issue_add.rhtml b/redmine/app/views/mailer/issue_add.rhtml deleted file mode 100644 index 9efec9ad9..000000000 --- a/redmine/app/views/mailer/issue_add.rhtml +++ /dev/null @@ -1,3 +0,0 @@ -Issue #<%= @issue.id %> has been reported. ----------------------------------------- -<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> \ No newline at end of file diff --git a/redmine/app/views/mailer/issue_add_en.rhtml b/redmine/app/views/mailer/issue_add_en.rhtml new file mode 100644 index 000000000..9efec9ad9 --- /dev/null +++ b/redmine/app/views/mailer/issue_add_en.rhtml @@ -0,0 +1,3 @@ +Issue #<%= @issue.id %> has been reported. +---------------------------------------- +<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> \ No newline at end of file diff --git a/redmine/app/views/mailer/issue_add_fr.rhtml b/redmine/app/views/mailer/issue_add_fr.rhtml new file mode 100644 index 000000000..628ecae12 --- /dev/null +++ b/redmine/app/views/mailer/issue_add_fr.rhtml @@ -0,0 +1,3 @@ +Une nouvelle demande (#<%= @issue.id %>) a été soumise. +---------------------------------------- +<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> \ No newline at end of file diff --git a/redmine/app/views/mailer/issue_change_status.rhtml b/redmine/app/views/mailer/issue_change_status.rhtml deleted file mode 100644 index e3612ea81..000000000 --- a/redmine/app/views/mailer/issue_change_status.rhtml +++ /dev/null @@ -1,3 +0,0 @@ -Issue #<%= @issue.id %> has been updated to "<%= @issue.status.name %>" status. ----------------------------------------- -<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> \ No newline at end of file diff --git a/redmine/app/views/mailer/issue_change_status_en.rhtml b/redmine/app/views/mailer/issue_change_status_en.rhtml new file mode 100644 index 000000000..e3612ea81 --- /dev/null +++ b/redmine/app/views/mailer/issue_change_status_en.rhtml @@ -0,0 +1,3 @@ +Issue #<%= @issue.id %> has been updated to "<%= @issue.status.name %>" status. +---------------------------------------- +<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> \ No newline at end of file diff --git a/redmine/app/views/mailer/issue_change_status_fr.rhtml b/redmine/app/views/mailer/issue_change_status_fr.rhtml new file mode 100644 index 000000000..831f301d5 --- /dev/null +++ b/redmine/app/views/mailer/issue_change_status_fr.rhtml @@ -0,0 +1,3 @@ +La demande #<%= @issue.id %> a été mise à jour au statut "<%= @issue.status.name %>". +---------------------------------------- +<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> \ No newline at end of file diff --git a/redmine/app/views/mailer/lost_password_en.rhtml b/redmine/app/views/mailer/lost_password_en.rhtml new file mode 100644 index 000000000..2593edbda --- /dev/null +++ b/redmine/app/views/mailer/lost_password_en.rhtml @@ -0,0 +1,3 @@ +To change your password, use the following link: + +http://<%= $RDM_HOST_NAME %>/account/lost_password?token=<%= @token.value %> \ No newline at end of file diff --git a/redmine/app/views/mailer/lost_password_fr.rhtml b/redmine/app/views/mailer/lost_password_fr.rhtml new file mode 100644 index 000000000..30996f118 --- /dev/null +++ b/redmine/app/views/mailer/lost_password_fr.rhtml @@ -0,0 +1,3 @@ +Pour changer votre mot de passe, utilisez le lien suivant: + +http://<%= $RDM_HOST_NAME %>/account/lost_password?token=<%= @token.value %> \ No newline at end of file diff --git a/redmine/app/views/mailer/register_en.rhtml b/redmine/app/views/mailer/register_en.rhtml new file mode 100644 index 000000000..2c0341b24 --- /dev/null +++ b/redmine/app/views/mailer/register_en.rhtml @@ -0,0 +1,3 @@ +To activate your redMine account, use the following link: + +http://<%= $RDM_HOST_NAME %>/account/register?token=<%= @token.value %> \ No newline at end of file diff --git a/redmine/app/views/mailer/register_fr.rhtml b/redmine/app/views/mailer/register_fr.rhtml new file mode 100644 index 000000000..3f5d0ccaf --- /dev/null +++ b/redmine/app/views/mailer/register_fr.rhtml @@ -0,0 +1,3 @@ +Pour activer votre compte sur redMine, utilisez le lien suivant: + +http://<%= $RDM_HOST_NAME %>/account/register?token=<%= @token.value %> \ No newline at end of file diff --git a/redmine/app/views/news/_form.rhtml b/redmine/app/views/news/_form.rhtml index 609b15cd9..ea6d5df7f 100644 --- a/redmine/app/views/news/_form.rhtml +++ b/redmine/app/views/news/_form.rhtml @@ -4,10 +4,10 @@

*
<%= text_field 'news', 'title', :size => 60 %>

-


-<%= text_area 'news', 'shortdescr', :cols => 60, :rows => 2 %>

+


+<%= text_area 'news', 'summary', :cols => 60, :rows => 2 %>

-


-<%= text_area 'news', 'descr', :cols => 60, :rows => 10 %>

+


+<%= text_area 'news', 'description', :cols => 60, :rows => 10 %>

diff --git a/redmine/app/views/news/show.rhtml b/redmine/app/views/news/show.rhtml index d6773cda9..f571b54ca 100644 --- a/redmine/app/views/news/show.rhtml +++ b/redmine/app/views/news/show.rhtml @@ -1,10 +1,10 @@

<%= @news.title %>

-<%=_('Summary')%>: <%= @news.shortdescr %>
+<%=_('Summary')%>: <%= @news.summary %>
<%=_('By')%>: <%= @news.author.display_name %>
<%=_('Date')%>: <%= format_time(@news.created_on) %>

-<%= simple_format auto_link @news.descr %> +<%= simple_format auto_link @news.description %> diff --git a/redmine/app/views/projects/_form.rhtml b/redmine/app/views/projects/_form.rhtml index 89f58354e..9623a9d46 100644 --- a/redmine/app/views/projects/_form.rhtml +++ b/redmine/app/views/projects/_form.rhtml @@ -1,10 +1,11 @@ <%= error_messages_for 'project' %> +


<%= text_field 'project', 'name' %>

-<% if session[:user].admin %> +<% if admin_loggedin? %>


<% end %> -


-<%= text_area 'project', 'descr', :cols => 60, :rows => 3 %>

+


+<%= text_area 'project', 'description', :cols => 60, :rows => 3 %>


<%= text_field 'project', 'homepage', :size => 40 %>

<%= check_box 'project', 'is_public' %>

- + +<% for custom_value in @custom_values %> +

<%= custom_field_tag_with_label custom_value %>

+<% end %> +
<%=_('Custom fields')%> <% for custom_field in @custom_fields %> <%= custom_field.name %> <% end %>
-
- + +
diff --git a/redmine/app/views/projects/add.rhtml b/redmine/app/views/projects/add.rhtml index 6344705b0..bdfe0862e 100644 --- a/redmine/app/views/projects/add.rhtml +++ b/redmine/app/views/projects/add.rhtml @@ -4,4 +4,3 @@ <%= render :partial => 'form' %> <%= submit_tag _('Create') %> <%= end_form_tag %> - diff --git a/redmine/app/views/projects/add_document.rhtml b/redmine/app/views/projects/add_document.rhtml index 13e75dd77..f1adc8d4d 100644 --- a/redmine/app/views/projects/add_document.rhtml +++ b/redmine/app/views/projects/add_document.rhtml @@ -12,8 +12,8 @@


<%= text_field 'document', 'title', :size => 60 %>

-


-<%= text_area 'document', 'descr', :cols => 60, :rows => 5 %>

+


+<%= text_area 'document', 'description', :cols => 60, :rows => 5 %>


<%= file_field 'attachment', 'file' %>

diff --git a/redmine/app/views/projects/add_issue.rhtml b/redmine/app/views/projects/add_issue.rhtml index a6b37cc46..5e4d450ec 100644 --- a/redmine/app/views/projects/add_issue.rhtml +++ b/redmine/app/views/projects/add_issue.rhtml @@ -1,16 +1,12 @@ -

<%=_('New issue')%>

+

<%=_('New issue')%>: <%=_(@tracker.name)%>

<%= start_form_tag( { :action => 'add_issue', :id => @project }, :multipart => true) %> <%= error_messages_for 'issue' %> +
- -
-


-

-
+ +<%= hidden_field_tag 'tracker_id', @tracker.id %>


@@ -30,33 +26,26 @@



<%= text_field 'issue', 'subject', :size => 80 %>

-


-<%= text_area 'issue', 'descr', :cols => 60, :rows => 10 %>

- +


+<%= text_area 'issue', 'description', :cols => 60, :rows => 10 %>

-<% for custom_value in @custom_values %> -
-

<%= content_tag "label", custom_value.custom_field.name %> - <% if custom_value.custom_field.is_required? %>*<% end %> -
- <%= custom_field_tag custom_value %>

-
+<% for custom_value in @custom_values %> +

<%= custom_field_tag_with_label custom_value %>

<% end %> -


<%= file_field 'attachment', 'file' %>

-
+
+ <%= submit_tag _('Create') %> <%= end_form_tag %> \ No newline at end of file diff --git a/redmine/app/views/projects/changelog.rhtml b/redmine/app/views/projects/changelog.rhtml index 3be8fb0dc..5d2a588ea 100644 --- a/redmine/app/views/projects/changelog.rhtml +++ b/redmine/app/views/projects/changelog.rhtml @@ -3,7 +3,7 @@ <% fixed_issues = @fixed_issues.group_by {|i| i.fixed_version } %> <% fixed_issues.each do |version, issues| %>

<%= version.name %> - <%= format_date(version.effective_date) %>
- <%=h version.descr %>

+ <%=h version.description %>

-- cgit v1.2.3