Compare commits

...
63 Commits
Author SHA1 Message Date
Jean-Philippe Lang 90602ac6dc Merged r3309 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3319 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-01-17 10:29:17 +00:00
Jean-Philippe Lang 8bab5b4730 Fixed: Cannot create a new category on ticket creation/update page with 0.8.7 (#4400).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3304 e93f8b46-1217-0410-a6f0-8f06a7374b81
2010-01-10 13:49:09 +00:00
Jean-Philippe Lang be146d492a Backported r3080 from trunk (#4248).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3081 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-21 10:33:12 +00:00
Jean-Philippe Lang b49aaccdd6 Set version to 0.8.7.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3056 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-15 10:05:49 +00:00
Jean-Philippe Lang 5abb5bf6e1 Do not version control session_store.rb.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3055 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-15 10:05:30 +00:00
Eric Davis 638a9a264a Ported the session_store.rb generation task from trunk.
Loosely based on r2493 but adapted for Rails 2.1.2.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3054 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 20:19:09 +00:00
Eric Davis 051741f05c Merged r3051 from trunk with some changes for 0.8 sessions.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3053 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 20:19:03 +00:00
Eric Davis ce41d4f9b0 Merged r3050 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3052 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 20:18:57 +00:00
Eric Davis 540d204e9a Updated CHANGELOG
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3048 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 18:17:42 +00:00
Eric Davis 2fd4e56ecd Merged r3032 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3047 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 18:17:37 +00:00
Eric Davis 3d926660ba Merged r3009 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3046 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 18:17:31 +00:00
Eric Davis b19ba93966 Merged r3030 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3045 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 18:17:25 +00:00
Eric Davis 36cc9af651 Merged r3026 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3044 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-14 18:17:20 +00:00
Jean-Philippe Lang 58c24ef2c8 Version set to 0.8.6 and CHANGELOG updated.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3001 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-04 10:25:49 +00:00
Jean-Philippe Lang ff1b7f4832 Merged r2999 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@3000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-04 10:23:53 +00:00
Jean-Philippe Lang c12b96a89f Merged r2979 and r2980 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-04 10:11:47 +00:00
Jean-Philippe Lang 341a3d1ed6 Merged r2261 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2997 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-04 10:07:20 +00:00
Jean-Philippe Lang 4be1c1ad58 Merged r2894 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-04 10:03:06 +00:00
Jean-Philippe Lang eaf0ea0c23 Merged r2924 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-11-04 09:57:11 +00:00
Jean-Philippe Lang d09afa64c8 Merged r2986 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2987 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-10-29 18:16:50 +00:00
Jean-Philippe Lang 48ee58f6b9 Merged r2983 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2984 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-10-29 17:57:10 +00:00
Eric Davis 3601c13b3b Updated CHANGELOG
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2900 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-23 01:39:13 +00:00
Eric Davis 88c95e824f Merged r2818 and r2819 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2899 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-23 01:38:15 +00:00
Jean-Philippe Lang 6ecfcd84b7 Update version to 0.8.5.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2890 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-17 17:49:48 +00:00
Jean-Philippe Lang d884cc3870 CHANGELOG update
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2885 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-13 12:01:35 +00:00
Jean-Philippe Lang bdfee87349 Merged r2766 and r2783 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2884 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-13 11:58:48 +00:00
Jean-Philippe Lang 2ec385858f Merged r2722, r2771, r2772 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2883 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-13 11:53:27 +00:00
Jean-Philippe Lang 94488269d1 Merged r2768, r2773, r2774, r2775, r2796 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2882 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-13 11:46:39 +00:00
Jean-Philippe Lang 3d0fbea9fd Merged r2797, r2804, r2814, r2820, r2837, r2838 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2881 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-09-13 11:36:09 +00:00
Eric Davis 3d68b60063 Fixed a merge error in r2830, wrong hook variables where used.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2831 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-08-01 18:28:57 +00:00
Eric Davis 27b110a61b Merged r2829 from trunk
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2830 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-08-01 18:17:46 +00:00
Jean-Philippe Lang d6394b60a5 Merged r2794 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2795 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-06-28 11:57:04 +00:00
Eric Davis ffd720eec9 Merged r2790 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2791 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-06-14 16:23:56 +00:00
Jean-Philippe Lang 50c0cebe96 Merged r2763 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2764 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-25 18:14:15 +00:00
Jean-Philippe Lang 1342228771 Translations updates.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2753 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-17 14:05:55 +00:00
Jean-Philippe Lang 6872c5e0b9 Updates for 0.8.4 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2748 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-17 09:16:23 +00:00
Jean-Philippe Lang e27460a0a7 Backported r2740 to r2742 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2747 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-17 09:13:38 +00:00
Jean-Philippe Lang 3f6656a495 Merged r2697, r2720, r2723, r2724, r2727, r2745 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2746 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-17 08:57:38 +00:00
Jean-Philippe Lang a3f69e248a Merged r2718 from trunk (#3291).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2719 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-10 08:40:51 +00:00
Eric Davis 3022d067ba Merged r2713 from trunk. #3086
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2714 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-06 04:57:52 +00:00
Jean-Philippe Lang e06987ab52 Merged r2707 and r2708 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2709 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-04 17:39:57 +00:00
Jean-Philippe Lang ace65df230 Merged r2705 from trunk (#3291).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2706 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-05-04 16:50:03 +00:00
Jean-Philippe Lang c5dadfd322 Backported r2690 from trunk (#3229).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2691 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-25 09:09:50 +00:00
Eric Davis 7a59f2df12 Merged r2686, r2687 from trunk
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2688 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-24 21:30:05 +00:00
Jean-Philippe Lang 7b699af837 Merged r2664, r2665, r2670, r2674, r2677, r2679 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2681 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-24 16:13:35 +00:00
Jean-Philippe Lang babbe88a86 Updates for 0.8.3 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2657 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 12:45:51 +00:00
Jean-Philippe Lang 51a9f6a6eb Merged r2655 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2656 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 12:35:34 +00:00
Jean-Philippe Lang 16810acf01 Merged r2610, r2611 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2654 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 12:16:34 +00:00
Jean-Philippe Lang e28b5e1f08 Merged r2643 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2653 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 12:09:59 +00:00
Jean-Philippe Lang aa38f755c6 Backported r2609 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2652 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 12:07:55 +00:00
Jean-Philippe Lang 2679cc2045 Merged r2574, r2578, r2589, r2615, r2641, r2645, r2646 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2651 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 12:03:03 +00:00
Jean-Philippe Lang b6600d5fe9 Merged r2563, r2566, r2567, r2568, r2569, r2582 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2650 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-04-05 11:52:49 +00:00
Jean-Philippe Lang 37da5ba187 Backported r2573, r2591 and r2592 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2593 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-15 10:10:39 +00:00
Jean-Philippe Lang 20bdba13cf Updates for 0.8.2 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2560 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-07 12:07:06 +00:00
Jean-Philippe Lang 46c0d72782 Merged r2259 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2559 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-07 12:02:08 +00:00
Jean-Philippe Lang 36b5d4f6af Backported r2429, r2430, r248 to r2491 and r2522 from trunk (request and controller objects added to the hooks by default.).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2558 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-07 11:43:38 +00:00
Jean-Philippe Lang b366375e7e Merged r2553 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2557 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-07 11:22:56 +00:00
Jean-Philippe Lang 629c106a46 Merged r2515, r2516, r2527, r2534, r2555 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2556 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-07 11:17:23 +00:00
Eric Davis f19ae06a72 Merged r2428 from trunk
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2548 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-03-04 00:03:06 +00:00
Jean-Philippe Lang 69b99aa518 Merged r2520 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2521 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-23 17:36:32 +00:00
Jean-Philippe Lang cb5d0c469d Merged r2487, r2488 and r2507 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2514 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-22 10:00:25 +00:00
Jean-Philippe Lang 57d10ed893 Merged r2262, r2341 and r2486 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2513 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-21 19:29:33 +00:00
Jean-Philippe Lang 28e4ff8957 Merged r2426 and r2484 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2512 e93f8b46-1217-0410-a6f0-8f06a7374b81
2009-02-21 19:22:31 +00:00
112 changed files with 1041 additions and 176 deletions
+6 -1
View File
@@ -35,6 +35,10 @@ class AccountController < ApplicationController
events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10) events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
@events_by_day = events.group_by(&:event_date) @events_by_day = events.group_by(&:event_date)
if @user != User.current && !User.current.admin? && @memberships.empty? && events.empty?
render_404 and return
end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
@@ -63,6 +67,7 @@ class AccountController < ApplicationController
token = Token.create(:user => user, :action => 'autologin') token = Token.create(:user => user, :action => 'autologin')
cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now } cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
end end
call_hook(:controller_account_success_authentication_after, {:user => user })
redirect_back_or_default :controller => 'my', :action => 'page' redirect_back_or_default :controller => 'my', :action => 'page'
end end
end end
@@ -183,12 +188,12 @@ class AccountController < ApplicationController
private private
def logged_user=(user) def logged_user=(user)
reset_session
if user && user.is_a?(User) if user && user.is_a?(User)
User.current = user User.current = user
session[:user_id] = user.id session[:user_id] = user.id
else else
User.current = User.anonymous User.current = User.anonymous
session[:user_id] = nil
end end
end end
end end
+14 -1
View File
@@ -19,10 +19,17 @@ require 'uri'
require 'cgi' require 'cgi'
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
class MissingSessionSecret < Exception ; end
layout 'base' layout 'base'
before_filter :user_setup, :check_if_login_required, :set_localization before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password filter_parameter_logging :password
if session.first[:secret].blank?
raise MissingSessionSecret, "Missing session secret. Please run 'rake config/initializers/session_store.rb' to generate one"
else
protect_from_forgery :secret => session.first[:secret]
end
include Redmine::MenuManager::MenuController include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper helper Redmine::MenuManager::MenuHelper
@@ -82,7 +89,13 @@ class ApplicationController < ActionController::Base
def require_login def require_login
if !User.current.logged? if !User.current.logged?
redirect_to :controller => "account", :action => "login", :back_url => url_for(params) # Extract only the basic url parameters on non-GET requests
if request.get?
url = url_for(params)
else
url = url_for(:controller => params[:controller], :action => params[:action], :id => params[:id], :project_id => params[:project_id])
end
redirect_to :controller => "account", :action => "login", :back_url => url
return false return false
end end
true true
@@ -46,6 +46,7 @@ class CustomFieldsController < ApplicationController
end end
if request.post? and @custom_field.save if request.post? and @custom_field.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'list', :tab => @custom_field.class.name redirect_to :action => 'list', :tab => @custom_field.class.name
end end
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
@@ -58,6 +59,7 @@ class CustomFieldsController < ApplicationController
@custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : [] @custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
end end
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'list', :tab => @custom_field.class.name redirect_to :action => 'list', :tab => @custom_field.class.name
end end
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
+11 -3
View File
@@ -23,7 +23,7 @@ class IssuesController < ApplicationController
before_filter :find_project, :only => [:new, :update_form, :preview] before_filter :find_project, :only => [:new, :update_form, :preview]
before_filter :authorize, :except => [:index, :changes, :gantt, :calendar, :preview, :update_form, :context_menu] before_filter :authorize, :except => [:index, :changes, :gantt, :calendar, :preview, :update_form, :context_menu]
before_filter :find_optional_project, :only => [:index, :changes, :gantt, :calendar] before_filter :find_optional_project, :only => [:index, :changes, :gantt, :calendar]
accept_key_auth :index, :changes accept_key_auth :index, :show, :changes
helper :journals helper :journals
helper :projects helper :projects
@@ -43,6 +43,10 @@ class IssuesController < ApplicationController
helper :timelog helper :timelog
include Redmine::Export::PDF include Redmine::Export::PDF
verify :method => :post,
:only => :destroy,
:render => { :nothing => true, :status => :method_not_allowed }
def index def index
retrieve_query retrieve_query
sort_init 'id', 'desc' sort_init 'id', 'desc'
@@ -147,6 +151,7 @@ class IssuesController < ApplicationController
attach_files(@issue, params[:attachments]) attach_files(@issue, params[:attachments])
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added') Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added')
call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
redirect_to(params[:continue] ? { :action => 'new', :tracker_id => @issue.tracker } : redirect_to(params[:continue] ? { :action => 'new', :tracker_id => @issue.tracker } :
{ :action => 'show', :id => @issue }) { :action => 'show', :id => @issue })
return return
@@ -194,6 +199,7 @@ class IssuesController < ApplicationController
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated') Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
end end
call_hook(:controller_issues_edit_after_save, { :params => params, :issue => @issue, :time_entry => @time_entry, :journal => journal})
redirect_to(params[:back_to] || {:action => 'show', :id => @issue}) redirect_to(params[:back_to] || {:action => 'show', :id => @issue})
end end
end end
@@ -343,10 +349,12 @@ class IssuesController < ApplicationController
@gantt.events = events @gantt.events = events
end end
basename = (@project ? "#{@project.identifier}-" : '') + 'gantt'
respond_to do |format| respond_to do |format|
format.html { render :template => "issues/gantt.rhtml", :layout => !request.xhr? } format.html { render :template => "issues/gantt.rhtml", :layout => !request.xhr? }
format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{@project.identifier}-gantt.png") } if @gantt.respond_to?('to_image') format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{basename}.png") } if @gantt.respond_to?('to_image')
format.pdf { send_data(gantt_to_pdf(@gantt, @project), :type => 'application/pdf', :filename => "#{@project.nil? ? '' : "#{@project.identifier}-" }gantt.pdf") } format.pdf { send_data(gantt_to_pdf(@gantt, @project), :type => 'application/pdf', :filename => "#{basename}.pdf") }
end end
end end
+2
View File
@@ -46,6 +46,7 @@ class MessagesController < ApplicationController
@message.sticky = params[:message]['sticky'] @message.sticky = params[:message]['sticky']
end end
if request.post? && @message.save if request.post? && @message.save
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
attach_files(@message, params[:attachments]) attach_files(@message, params[:attachments])
redirect_to :action => 'show', :id => @message redirect_to :action => 'show', :id => @message
end end
@@ -58,6 +59,7 @@ class MessagesController < ApplicationController
@reply.board = @board @reply.board = @board
@topic.children << @reply @topic.children << @reply
if !@reply.new_record? if !@reply.new_record?
call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
attach_files(@reply, params[:attachments]) attach_files(@reply, params[:attachments])
end end
redirect_to :action => 'show', :id => @topic redirect_to :action => 'show', :id => @topic
+1
View File
@@ -65,6 +65,7 @@ class NewsController < ApplicationController
flash[:notice] = l(:label_comment_added) flash[:notice] = l(:label_comment_added)
redirect_to :action => 'show', :id => @news redirect_to :action => 'show', :id => @news
else else
show
render :action => 'show' render :action => 'show'
end end
end end
+4 -1
View File
@@ -88,7 +88,7 @@ class TimelogController < ApplicationController
sql << " WHERE" sql << " WHERE"
sql << " (%s) AND" % @project.project_condition(Setting.display_subprojects_issues?) if @project sql << " (%s) AND" % @project.project_condition(Setting.display_subprojects_issues?) if @project
sql << " (%s) AND" % Project.allowed_to_condition(User.current, :view_time_entries) sql << " (%s) AND" % Project.allowed_to_condition(User.current, :view_time_entries)
sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from.to_time), ActiveRecord::Base.connection.quoted_date(@to.to_time)] sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)]
sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on" sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on"
@hours = ActiveRecord::Base.connection.select_all(sql) @hours = ActiveRecord::Base.connection.select_all(sql)
@@ -197,6 +197,9 @@ class TimelogController < ApplicationController
render_403 and return if @time_entry && !@time_entry.editable_by?(User.current) render_403 and return if @time_entry && !@time_entry.editable_by?(User.current)
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today) @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
@time_entry.attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if request.post? and @time_entry.save if request.post? and @time_entry.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_back_or_default :action => 'details', :project_id => @time_entry.project redirect_back_or_default :action => 'details', :project_id => @time_entry.project
+5 -1
View File
@@ -75,7 +75,11 @@ class UsersController < ApplicationController
@user.admin = params[:user][:admin] if params[:user][:admin] @user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login] @user.login = params[:user][:login] if params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
if @user.update_attributes(params[:user]) @user.attributes = params[:user]
# Was the account actived ? (do it before User#save clears the change)
was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
if @user.save
Mailer.deliver_account_activated(@user) if was_activated
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
# Give a string to redirect_to otherwise it would use status param as the response code # Give a string to redirect_to otherwise it would use status param as the response code
redirect_to(url_for(:action => 'list', :status => params[:status], :page => params[:page])) redirect_to(url_for(:action => 'list', :status => params[:status], :page => params[:page]))
+1
View File
@@ -82,6 +82,7 @@ class WikiController < ApplicationController
@content.author = User.current @content.author = User.current
# if page is new @page.save will also save content, but not if page isn't a new record # if page is new @page.save will also save content, but not if page isn't a new record
if (@page.new_record? ? @page.save : @content.save) if (@page.new_record? ? @page.save : @content.save)
call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
redirect_to :action => 'index', :id => @project, :page => @page.title redirect_to :action => 'index', :id => @project, :page => @page.title
end end
end end
+7 -7
View File
@@ -159,7 +159,7 @@ module ApplicationHelper
# Truncates and returns the string as a single line # Truncates and returns the string as a single line
def truncate_single_line(string, *args) def truncate_single_line(string, *args)
truncate(string, *args).gsub(%r{[\r\n]+}m, ' ') truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
end end
def html_hours(text) def html_hours(text)
@@ -385,7 +385,7 @@ module ApplicationHelper
# export:some/file -> Force the download of the file # export:some/file -> Force the download of the file
# Forum messages: # Forum messages:
# message#1218 -> Link to message with id 1218 # message#1218 -> Link to message with id 1218
text = text.gsub(%r{([\s\(,\-\>]|^)(!)?(attachment|document|version|commit|source|export|message)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|\s|<|$)}) do |m| text = text.gsub(%r{([\s\(,\-\>]|^)(!)?(attachment|document|version|commit|source|export|message)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|<|$)}) do |m|
leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
link = nil link = nil
if esc.nil? if esc.nil?
@@ -487,11 +487,11 @@ module ApplicationHelper
full_messages = [] full_messages = []
object.errors.each do |attr, msg| object.errors.each do |attr, msg|
next if msg.nil? next if msg.nil?
msg = msg.first if msg.is_a? Array msg = [msg] unless msg.is_a?(Array)
if attr == "base" if attr == "base"
full_messages << l(msg) full_messages << l(*msg)
else else
full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values" full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(*msg) unless attr == "custom_values"
end end
end end
# retrieve custom values error messages # retrieve custom values error messages
@@ -499,8 +499,8 @@ module ApplicationHelper
object.custom_values.each do |v| object.custom_values.each do |v|
v.errors.each do |attr, msg| v.errors.each do |attr, msg|
next if msg.nil? next if msg.nil?
msg = msg.first if msg.is_a? Array msg = [msg] unless msg.is_a?(Array)
full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg) full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(*msg)
end end
end end
end end
+2
View File
@@ -38,6 +38,8 @@ module IssuesHelper
s = "issue status-#{issue.status.position} priority-#{issue.priority.position}" s = "issue status-#{issue.status.position} priority-#{issue.priority.position}"
s << ' closed' if issue.closed? s << ' closed' if issue.closed?
s << ' overdue' if issue.overdue? s << ' overdue' if issue.overdue?
s << ' created-by-me' if User.current.logged? && issue.author_id == User.current.id
s << ' assigned-to-me' if User.current.logged? && issue.assigned_to_id == User.current.id
s s
end end
+7 -1
View File
@@ -40,8 +40,14 @@ module QueriesHelper
else else
case column.name case column.name
when :subject when :subject
h((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') + h((!@project.nil? && @project != issue.project) ? "#{issue.project.name} - " : '') +
link_to(h(value), :controller => 'issues', :action => 'show', :id => issue) link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
when :project
link_to(h(value), :controller => 'projects', :action => 'show', :id => value)
when :assigned_to
link_to(h(value), :controller => 'account', :action => 'show', :id => value)
when :author
link_to(h(value), :controller => 'account', :action => 'show', :id => value)
when :done_ratio when :done_ratio
progress_bar(value, :width => '80px') progress_bar(value, :width => '80px')
when :fixed_version when :fixed_version
+1 -1
View File
@@ -147,7 +147,7 @@ module RepositoriesHelper
def subversion_field_tags(form, repository) def subversion_field_tags(form, repository)
content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) +
'<br />(http://, https://, svn://, file:///)') + '<br />(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
content_tag('p', form.text_field(:login, :size => 30)) + content_tag('p', form.text_field(:login, :size => 30)) +
content_tag('p', form.password_field(:password, :size => 30, :name => 'ignore', content_tag('p', form.password_field(:password, :size => 30, :name => 'ignore',
:value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)), :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)),
+5 -1
View File
@@ -35,7 +35,11 @@ module TimelogHelper
end end
def select_hours(data, criteria, value) def select_hours(data, criteria, value)
data.select {|row| row[criteria] == value} if value.to_s.empty?
data.select {|row| row[criteria].blank? }
else
data.select {|row| row[criteria] == value}
end
end end
def sum_hours(data) def sum_hours(data)
+1 -1
View File
@@ -36,7 +36,7 @@ module WikiHelper
words_add += 1 words_add += 1
else else
del_at = pos unless del_at del_at = pos unless del_at
deleted << ' ' + change[2] deleted << ' ' + h(change[2])
words_del += 1 words_del += 1
end end
end end
+10 -11
View File
@@ -33,7 +33,7 @@ class Attachment < ActiveRecord::Base
:author_key => :author_id, :author_key => :author_id,
:find_options => {:select => "#{Attachment.table_name}.*", :find_options => {:select => "#{Attachment.table_name}.*",
:joins => "LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " + :joins => "LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " +
"LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id"} "LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id OR ( #{Attachment.table_name}.container_type='Project' AND #{Attachment.table_name}.container_id = #{Project.table_name}.id )"}
acts_as_activity_provider :type => 'documents', acts_as_activity_provider :type => 'documents',
:permission => :view_documents, :permission => :view_documents,
@@ -65,14 +65,20 @@ class Attachment < ActiveRecord::Base
nil nil
end end
# Copy temp file to its final location # Copies the temporary file to its final location
# and computes its MD5 hash
def before_save def before_save
if @temp_file && (@temp_file.size > 0) if @temp_file && (@temp_file.size > 0)
logger.debug("saving '#{self.diskfile}'") logger.debug("saving '#{self.diskfile}'")
md5 = Digest::MD5.new
File.open(diskfile, "wb") do |f| File.open(diskfile, "wb") do |f|
f.write(@temp_file.read) buffer = ""
while (buffer = @temp_file.read(8192))
f.write(buffer)
md5.update(buffer)
end
end end
self.digest = self.class.digest(diskfile) self.digest = md5.hexdigest
end end
# Don't save the content type if it's longer than the authorized length # Don't save the content type if it's longer than the authorized length
if self.content_type && self.content_type.length > 255 if self.content_type && self.content_type.length > 255
@@ -141,11 +147,4 @@ private
end end
df df
end end
# Returns the MD5 digest of the file at given path
def self.digest(filename)
File.open(filename, 'rb') do |f|
Digest::MD5.hexdigest(f.read)
end
end
end end
+2
View File
@@ -112,6 +112,8 @@ class Changeset < ActiveRecord::Base
journal = issue.init_journal(user || User.anonymous, l(:text_status_changed_by_changeset, csettext)) journal = issue.init_journal(user || User.anonymous, l(:text_status_changed_by_changeset, csettext))
issue.status = fix_status issue.status = fix_status
issue.done_ratio = done_ratio if done_ratio issue.done_ratio = done_ratio if done_ratio
Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
{ :changeset => self, :issue => issue })
issue.save issue.save
Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated') Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
end end
+1 -1
View File
@@ -38,7 +38,7 @@ class Journal < ActiveRecord::Base
:conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" + :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" +
" (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"} " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"}
def save def save(*args)
# Do not save an empty journal # Do not save an empty journal
(details.empty? && notes.blank?) ? false : super (details.empty? && notes.blank?) ? false : super
end end
+13 -5
View File
@@ -40,7 +40,7 @@ class MailHandler < ActionMailer::Base
# Processes incoming emails # Processes incoming emails
def receive(email) def receive(email)
@email = email @email = email
@user = User.active.find(:first, :conditions => ["LOWER(mail) = ?", email.from.first.to_s.strip.downcase]) @user = User.active.find(:first, :conditions => ["LOWER(mail) = ?", email.from.to_a.first.to_s.strip.downcase])
unless @user unless @user
# Unknown user => the email is ignored # Unknown user => the email is ignored
# TODO: ability to create the user's account # TODO: ability to create the user's account
@@ -163,10 +163,17 @@ class MailHandler < ActionMailer::Base
end end
def get_keyword(attr, options={}) def get_keyword(attr, options={})
if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i @keywords ||= {}
$1.strip if @keywords.has_key?(attr)
elsif !@@handler_options[:issue][attr].blank? @keywords[attr]
@@handler_options[:issue][attr] else
@keywords[attr] = begin
if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && plain_text_body.gsub!(/^#{attr}[ \t]*:[ \t]*(.+)\s*$/i, '')
$1.strip
elsif !@@handler_options[:issue][attr].blank?
@@handler_options[:issue][attr]
end
end
end end
end end
@@ -188,5 +195,6 @@ class MailHandler < ActionMailer::Base
@plain_text_body = plain_text_part.body.to_s @plain_text_body = plain_text_part.body.to_s
end end
@plain_text_body.strip! @plain_text_body.strip!
@plain_text_body
end end
end end
+18 -7
View File
@@ -22,6 +22,12 @@ class Mailer < ActionMailer::Base
include ActionController::UrlWriter include ActionController::UrlWriter
def self.default_url_options
h = Setting.host_name
h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
{ :host => h, :protocol => Setting.protocol }
end
def issue_add(issue) def issue_add(issue)
redmine_headers 'Project' => issue.project.identifier, redmine_headers 'Project' => issue.project.identifier,
'Issue-Id' => issue.id, 'Issue-Id' => issue.id,
@@ -127,6 +133,15 @@ class Mailer < ActionMailer::Base
:url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc') :url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
end end
# A registered user's account was activated by an administrator
def account_activated(user)
set_language_if_valid user.language
recipients user.mail
subject l(:mail_subject_register, Setting.app_title)
body :user => user,
:login_url => url_for(:controller => 'account', :action => 'login')
end
def lost_password(token) def lost_password(token)
set_language_if_valid(token.user.language) set_language_if_valid(token.user.language)
recipients token.user.mail recipients token.user.mail
@@ -189,16 +204,12 @@ class Mailer < ActionMailer::Base
set_language_if_valid Setting.default_language set_language_if_valid Setting.default_language
from Setting.mail_from from Setting.mail_from
# URL options
h = Setting.host_name
h = h.to_s.gsub(%r{\/.*$}, '') unless ActionController::AbstractRequest.relative_url_root.blank?
default_url_options[:host] = h
default_url_options[:protocol] = Setting.protocol
# Common headers # Common headers
headers 'X-Mailer' => 'Redmine', headers 'X-Mailer' => 'Redmine',
'X-Redmine-Host' => Setting.host_name, 'X-Redmine-Host' => Setting.host_name,
'X-Redmine-Site' => Setting.app_title 'X-Redmine-Site' => Setting.app_title,
'Precedence' => 'bulk',
'Auto-Submitted' => 'auto-generated'
end end
# Appends a Redmine header field (name is prepended with 'X-Redmine-') # Appends a Redmine header field (name is prepended with 'X-Redmine-')
+1 -1
View File
@@ -24,7 +24,7 @@ class News < ActiveRecord::Base
validates_length_of :title, :maximum => 60 validates_length_of :title, :maximum => 60
validates_length_of :summary, :maximum => 255 validates_length_of :summary, :maximum => 255
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
acts_as_activity_provider :find_options => {:include => [:project, :author]}, acts_as_activity_provider :find_options => {:include => [:project, :author]},
:author_key => :author_id :author_key => :author_id
+1 -1
View File
@@ -60,7 +60,7 @@ class Project < ActiveRecord::Base
validates_associated :repository, :wiki validates_associated :repository, :wiki
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_length_of :homepage, :maximum => 255 validates_length_of :homepage, :maximum => 255
validates_length_of :identifier, :in => 2..20 validates_length_of :identifier, :in => 1..20
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/ validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
before_destroy :delete_all_members before_destroy :delete_all_members
+7 -3
View File
@@ -93,6 +93,7 @@ class Query < ActiveRecord::Base
cattr_reader :operators_by_filter_type cattr_reader :operators_by_filter_type
@@available_columns = [ @@available_columns = [
QueryColumn.new(:project, :sortable => "#{Project.table_name}.name"),
QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position"), QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position"),
QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.position"), QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.position"),
QueryColumn.new(:priority, :sortable => "#{Enumeration.table_name}.position", :default_order => 'desc'), QueryColumn.new(:priority, :sortable => "#{Enumeration.table_name}.position", :default_order => 'desc'),
@@ -234,7 +235,10 @@ class Query < ActiveRecord::Base
def columns def columns
if has_default_columns? if has_default_columns?
available_columns.select {|c| Setting.issue_list_default_columns.include?(c.name.to_s) } available_columns.select do |c|
# Adds the project column by default for cross-project lists
Setting.issue_list_default_columns.include?(c.name.to_s) || (c.name == :project && project.nil?)
end
else else
# preserve the column_names order # preserve the column_names order
column_names.collect {|name| available_columns.find {|col| col.name == name}}.compact column_names.collect {|name| available_columns.find {|col| col.name == name}}.compact
@@ -364,9 +368,9 @@ class Query < ActiveRecord::Base
Time.now.at_beginning_of_week Time.now.at_beginning_of_week
sql = "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(from), connection.quoted_date(from + 7.days)] sql = "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(from), connection.quoted_date(from + 7.days)]
when "~" when "~"
sql = "#{db_table}.#{db_field} LIKE '%#{connection.quote_string(value.first)}%'" sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
when "!~" when "!~"
sql = "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(value.first)}%'" sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
end end
return sql return sql
+4 -4
View File
@@ -20,7 +20,7 @@ require 'redmine/scm/adapters/subversion_adapter'
class Repository::Subversion < Repository class Repository::Subversion < Repository
attr_protected :root_url attr_protected :root_url
validates_presence_of :url validates_presence_of :url
validates_format_of :url, :with => /^(http|https|svn|svn\+ssh|file):\/\/.+/i validates_format_of :url, :with => /^(http|https|svn(\+[^\s:\/\\]+)?|file):\/\/.+/i
def scm_adapter def scm_adapter
Redmine::Scm::Adapters::SubversionAdapter Redmine::Scm::Adapters::SubversionAdapter
@@ -54,8 +54,8 @@ class Repository::Subversion < Repository
# loads changesets by batches of 200 # loads changesets by batches of 200
identifier_to = [identifier_from + 199, scm_revision].min identifier_to = [identifier_from + 199, scm_revision].min
revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true) revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
transaction do revisions.reverse_each do |revision|
revisions.reverse_each do |revision| transaction do
changeset = Changeset.create(:repository => self, changeset = Changeset.create(:repository => self,
:revision => revision.identifier, :revision => revision.identifier,
:committer => revision.author, :committer => revision.author,
@@ -68,7 +68,7 @@ class Repository::Subversion < Repository
:path => change[:path], :path => change[:path],
:from_path => change[:from_path], :from_path => change[:from_path],
:from_revision => change[:from_revision]) :from_revision => change[:from_revision])
end end unless changeset.new_record?
end end
end unless revisions.nil? end unless revisions.nil?
identifier_from = identifier_to + 1 identifier_from = identifier_to + 1
+5 -4
View File
@@ -15,8 +15,11 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'rails_generator/secret_key_generator'
class Token < ActiveRecord::Base class Token < ActiveRecord::Base
belongs_to :user belongs_to :user
validates_uniqueness_of :value
@@validity_time = 1.day @@validity_time = 1.day
@@ -36,9 +39,7 @@ class Token < ActiveRecord::Base
private private
def self.generate_token_value def self.generate_token_value
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a s = Rails::SecretKeyGenerator.new(object_id).generate_secret
token_value = '' s[0, 40]
40.times { |i| token_value << chars[rand(chars.size-1)] }
token_value
end end
end end
+8 -2
View File
@@ -175,8 +175,14 @@ class User < ActiveRecord::Base
end end
def self.find_by_autologin_key(key) def self.find_by_autologin_key(key)
token = Token.find_by_action_and_value('autologin', key) tokens = Token.find_all_by_action_and_value('autologin', key)
token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil # Make sure there's only 1 token that matches the key
if tokens.size == 1
token = tokens.first
if (token.created_on > Setting.autologin.to_i.day.ago) && token.user && token.user.active?
token.user
end
end
end end
# Makes find_by_mail case-insensitive # Makes find_by_mail case-insensitive
+1
View File
@@ -22,6 +22,7 @@ class WikiContent < ActiveRecord::Base
belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id' belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :text validates_presence_of :text
validates_length_of :comments, :maximum => 255, :allow_nil => true
acts_as_versioned acts_as_versioned
class Version class Version
+3 -1
View File
@@ -10,7 +10,7 @@
<li><%=l(:field_mail)%>: <%= mail_to(h(@user.mail), nil, :encode => 'javascript') %></li> <li><%=l(:field_mail)%>: <%= mail_to(h(@user.mail), nil, :encode => 'javascript') %></li>
<% end %> <% end %>
<% for custom_value in @custom_values %> <% for custom_value in @custom_values %>
<% if !custom_value.value.empty? %> <% if !custom_value.value.blank? %>
<li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li> <li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
<% end %> <% end %>
<% end %> <% end %>
@@ -29,6 +29,7 @@
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
<%= call_hook :view_account_left_bottom, :user => @user %>
</div> </div>
<div class="splitcontentright"> <div class="splitcontentright">
@@ -64,6 +65,7 @@
<%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :user_id => @user, :format => :atom, :key => User.current.rss_key) %> <%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :user_id => @user, :format => :atom, :key => User.current.rss_key) %>
<% end %> <% end %>
<% end %> <% end %>
<%= call_hook :view_account_right_bottom, :user => @user %>
</div> </div>
<% html_title @user.name %> <% html_title @user.name %>
+1 -1
View File
@@ -11,7 +11,7 @@ while day <= calendar.enddt %>
<p class="day-num"><%= day.day %></p> <p class="day-num"><%= day.day %></p>
<% calendar.events_on(day).each do |i| %> <% calendar.events_on(day).each do |i| %>
<% if i.is_a? Issue %> <% if i.is_a? Issue %>
<div class="tooltip"> <div class="<%= css_issue_classes(i) %> tooltip">
<%= if day == i.start_date && day == i.due_date <%= if day == i.start_date && day == i.due_date
image_tag('arrow_bw.png') image_tag('arrow_bw.png')
elsif day == i.start_date elsif day == i.start_date
+1 -1
View File
@@ -3,7 +3,7 @@
<tbody> <tbody>
<% line_num = 1 %> <% line_num = 1 %>
<% syntax_highlight(filename, to_utf8(content)).each_line do |line| %> <% syntax_highlight(filename, to_utf8(content)).each_line do |line| %>
<tr><th class="line-num" id="L<%= line_num %>"><%= line_num %></th><td class="line-code"><pre><%= line %></pre></td></tr> <tr><th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th><td class="line-code"><pre><%= line %></pre></td></tr>
<% line_num += 1 %> <% line_num += 1 %>
<% end %> <% end %>
</tbody> </tbody>
+4 -4
View File
@@ -1,8 +1,8 @@
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.title truncate_single_line(@title, 100) xml.title truncate_single_line(@title, 100)
xml.link "rel" => "self", "href" => url_for(params.merge({:format => nil, :only_path => false})) xml.link "rel" => "self", "href" => url_for(params.merge(:only_path => false))
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false) xml.link "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil))
xml.id url_for(:controller => 'welcome', :only_path => false) xml.id url_for(:controller => 'welcome', :only_path => false)
xml.updated((@items.first ? @items.first.event_datetime : Time.now).xmlschema) xml.updated((@items.first ? @items.first.event_datetime : Time.now).xmlschema)
xml.author { xml.name "#{Setting.app_title}" } xml.author { xml.name "#{Setting.app_title}" }
@@ -21,10 +21,10 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
author = item.event_author if item.respond_to?(:event_author) author = item.event_author if item.respond_to?(:event_author)
xml.author do xml.author do
xml.name(author) xml.name(author)
xml.email(author.mail) if author.respond_to?(:mail) && !author.mail.blank? xml.email(author.mail) if author.is_a?(User) && !author.mail.blank? && !author.pref.hide_mail
end if author end if author
xml.content "type" => "html" do xml.content "type" => "html" do
xml.text! textilizable(item.event_description) xml.text! textilizable(item, :event_description, :only_path => false)
end end
end end
end end
+2
View File
@@ -82,6 +82,7 @@ function deleteValueField(e) {
<% end %> <% end %>
</p> </p>
<p><%= @custom_field.field_format == 'bool' ? f.check_box(:default_value) : f.text_field(:default_value) %></p> <p><%= @custom_field.field_format == 'bool' ? f.check_box(:default_value) : f.text_field(:default_value) %></p>
<%= call_hook(:view_custom_fields_form_upper_box, :custom_field => @custom_field, :form => f) %>
</div> </div>
<div class="box"> <div class="box">
@@ -109,5 +110,6 @@ when "IssueCustomField" %>
<p><%= f.check_box :is_required %></p> <p><%= f.check_box :is_required %></p>
<% end %> <% end %>
<%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", :custom_field => @custom_field, :form => f) %>
</div> </div>
<%= javascript_tag "toggle_custom_field_format();" %> <%= javascript_tag "toggle_custom_field_format();" %>
+3 -1
View File
@@ -11,5 +11,7 @@
<p><label for="issue_status_is_default"><%=l(:field_is_default)%></label> <p><label for="issue_status_is_default"><%=l(:field_is_default)%></label>
<%= check_box 'issue_status', 'is_default' %></p> <%= check_box 'issue_status', 'is_default' %></p>
<%= call_hook(:view_issue_statuses_form, :issue_status => @issue_status) %>
<!--[eoform:issue_status]--> <!--[eoform:issue_status]-->
</div> </div>
+1 -1
View File
@@ -28,7 +28,7 @@
<p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %> <p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %>
<%= prompt_to_remote(l(:label_issue_category_new), <%= prompt_to_remote(l(:label_issue_category_new),
l(:label_issue_category_new), 'category[name]', l(:label_issue_category_new), 'category[name]',
{:controller => 'projects', :action => 'add_issue_category', :id => @project}, {:controller => 'projects', :action => 'add_issue_category', :id => @project, :authenticity_token => form_authenticity_token},
:class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p> :class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
<% end %> <% end %>
<%= content_tag('p', f.select(:fixed_version_id, <%= content_tag('p', f.select(:fixed_version_id,
+2 -2
View File
@@ -7,8 +7,8 @@
<%= call_hook(:view_issues_sidebar_issues_bottom) %> <%= call_hook(:view_issues_sidebar_issues_bottom) %>
<% planning_links = [] <% planning_links = []
planning_links << link_to(l(:label_calendar), :action => 'calendar', :project_id => @project) if User.current.allowed_to?(:view_calendar, @project, :global => true) planning_links << link_to(l(:label_calendar), :controller => 'issues', :action => 'calendar', :project_id => @project) if User.current.allowed_to?(:view_calendar, @project, :global => true)
planning_links << link_to(l(:label_gantt), :action => 'gantt', :project_id => @project) if User.current.allowed_to?(:view_gantt, @project, :global => true) planning_links << link_to(l(:label_gantt), :controller => 'issues', :action => 'gantt', :project_id => @project) if User.current.allowed_to?(:view_gantt, @project, :global => true)
%> %>
<% unless planning_links.empty? %> <% unless planning_links.empty? %>
<h3><%= l(:label_planning) %></h3> <h3><%= l(:label_planning) %></h3>
+2 -2
View File
@@ -15,7 +15,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.updated change.created_on.xmlschema xml.updated change.created_on.xmlschema
xml.author do xml.author do
xml.name change.user.name xml.name change.user.name
xml.email(change.user.mail) xml.email(change.user.mail) if change.user.is_a?(User) && !change.user.mail.blank? && !change.user.pref.hide_mail
end end
xml.content "type" => "html" do xml.content "type" => "html" do
xml.text! '<ul>' xml.text! '<ul>'
@@ -23,7 +23,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.text! '<li>' + show_detail(detail, false) + '</li>' xml.text! '<li>' + show_detail(detail, false) + '</li>'
end end
xml.text! '</ul>' xml.text! '</ul>'
xml.text! textilizable(change.notes) unless change.notes.blank? xml.text! textilizable(change, :notes, :only_path => false) unless change.notes.blank?
end end
end end
end end
+4
View File
@@ -1,4 +1,6 @@
<ul> <ul>
<%= call_hook(:view_issues_context_menu_start, {:issues => @issues, :can => @can, :back => @back }) %>
<% if !@issue.nil? -%> <% if !@issue.nil? -%>
<li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, <li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue},
:class => 'icon-edit', :disabled => !@can[:edit] %></li> :class => 'icon-edit', :disabled => !@can[:edit] %></li>
@@ -87,4 +89,6 @@
:class => 'icon-move', :disabled => !@can[:move] %></li> :class => 'icon-move', :disabled => !@can[:move] %></li>
<li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)}, <li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)},
:method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %></li> :method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %></li>
<%= call_hook(:view_issues_context_menu_end, {:issues => @issues, :can => @can, :back => @back }) %>
</ul> </ul>
+1 -1
View File
@@ -42,6 +42,7 @@
<% else %> <% else %>
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
<p class="pagination"><%= pagination_links_full @issue_pages, @issue_count %></p> <p class="pagination"><%= pagination_links_full @issue_pages, @issue_count %></p>
<% end %>
<p class="other-formats"> <p class="other-formats">
<%= l(:label_export_to) %> <%= l(:label_export_to) %>
@@ -50,7 +51,6 @@
<span><%= link_to 'PDF', {:format => 'pdf'}, :class => 'pdf' %></span> <span><%= link_to 'PDF', {:format => 'pdf'}, :class => 'pdf' %></span>
</p> </p>
<% end %> <% end %>
<% end %>
<% content_for :sidebar do %> <% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %> <%= render :partial => 'issues/sidebar' %>
+4 -2
View File
@@ -9,7 +9,7 @@
<h2><%= @issue.tracker.name %> #<%= @issue.id %></h2> <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
<div class="<%= css_issue_classes(@issue) %>"> <div class="<%= css_issue_classes(@issue) %> details">
<%= avatar(@issue.author, :size => "64") %> <%= avatar(@issue.author, :size => "64") %>
<h3><%=h @issue.subject %></h3> <h3><%=h @issue.subject %></h3>
<p class="author"> <p class="author">
@@ -45,7 +45,7 @@
</tr> </tr>
<tr> <tr>
<% n = 0 -%> <% n = 0 -%>
<% @issue.custom_values.each do |value| -%> <% @issue.custom_field_values.each do |value| -%>
<td valign="top"><b><%=h value.custom_field.name %>:</b></td><td valign="top"><%= simple_format(h(show_value(value))) %></td> <td valign="top"><b><%=h value.custom_field.name %>:</b></td><td valign="top"><%= simple_format(h(show_value(value))) %></td>
<% n = n + 1 <% n = n + 1
if (n > 1) if (n > 1)
@@ -69,6 +69,8 @@ end %>
<%= link_to_attachments @issue %> <%= link_to_attachments @issue %>
<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
<% if authorize_for('issue_relations', 'new') || @issue.relations.any? %> <% if authorize_for('issue_relations', 'new') || @issue.relations.any? %>
<hr /> <hr />
<div id="relations"> <div id="relations">
+2 -2
View File
@@ -1,6 +1,6 @@
<% form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %> <% form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %>
<%= text_area_tag :notes, h(@journal.notes), :class => 'wiki-edit', <%= text_area_tag :notes, @journal.notes, :class => 'wiki-edit',
:rows => (@journal.notes.blank? ? 10 : [[10, @journal.notes.length / 50].max, 100].min) %> :rows => (@journal.notes.blank? ? 10 : [[10, @journal.notes.length / 50].max, 100].min) %>
<%= call_hook(:view_journals_notes_form_after_notes, { :journal => @journal}) %> <%= call_hook(:view_journals_notes_form_after_notes, { :journal => @journal}) %>
<p><%= submit_tag l(:button_save) %> <p><%= submit_tag l(:button_save) %>
<%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " + <%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " +
+3 -1
View File
@@ -47,18 +47,20 @@
<%= tag('div', {:id => 'main', :class => (has_content?(:sidebar) ? '' : 'nosidebar')}, true) %> <%= tag('div', {:id => 'main', :class => (has_content?(:sidebar) ? '' : 'nosidebar')}, true) %>
<div id="sidebar"> <div id="sidebar">
<%= yield :sidebar %> <%= yield :sidebar %>
<%= call_hook :view_layouts_base_sidebar %>
</div> </div>
<div id="content"> <div id="content">
<%= render_flash_messages %> <%= render_flash_messages %>
<%= yield %> <%= yield %>
<%= call_hook :view_layouts_base_content %>
</div> </div>
</div> </div>
<div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div> <div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div>
<div id="footer"> <div id="footer">
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> &copy; 2006-2008 Jean-Philippe Lang Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> &copy; 2006-2009 Jean-Philippe Lang
</div> </div>
</div> </div>
<%= call_hook :view_layouts_base_body_bottom %> <%= call_hook :view_layouts_base_body_bottom %>
@@ -0,0 +1,2 @@
<p><%= l(:notice_account_activated) %></p>
<p><%= l(:label_login) %>: <%= link_to @login_url, @login_url %></p>
@@ -0,0 +1,2 @@
<%= l(:notice_account_activated) %>
<%= l(:label_login) %>: <%= @login_url %>
+1 -1
View File
@@ -1,3 +1,3 @@
<%= yield %> <%= yield %>
---------------------------------------- --
<%= Setting.emails_footer %> <%= Setting.emails_footer %>
+1 -1
View File
@@ -2,7 +2,7 @@
<ul> <ul>
<% @issues.each do |issue| -%> <% @issues.each do |issue| -%>
<li><%=h "#{issue.project} - #{issue.tracker} ##{issue.id}: #{issue.subject}" %></li> <li><%=h issue.project %> - <%=link_to("#{issue.tracker} ##{issue.id}", :controller => 'issues', :action => 'show', :id => issue, :only_path => false)%>: <%=h issue.subject %></li>
<% end -%> <% end -%>
</ul> </ul>
+1
View File
@@ -15,6 +15,7 @@
<p><%= f.text_field :lastname, :required => true %></p> <p><%= f.text_field :lastname, :required => true %></p>
<p><%= f.text_field :mail, :required => true %></p> <p><%= f.text_field :mail, :required => true %></p>
<p><%= f.select :language, lang_options_for_select %></p> <p><%= f.select :language, lang_options_for_select %></p>
<%= call_hook(:view_my_account, :user => @user, :form => f) %>
</div> </div>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
+1 -1
View File
@@ -11,7 +11,7 @@
<p><%= f.text_area :description, :rows => 5, :class => 'wiki-edit' %></p> <p><%= f.text_area :description, :rows => 5, :class => 'wiki-edit' %></p>
<p><%= f.text_field :identifier, :required => true, :disabled => @project.identifier_frozen? %> <p><%= f.text_field :identifier, :required => true, :disabled => @project.identifier_frozen? %>
<% unless @project.identifier_frozen? %> <% unless @project.identifier_frozen? %>
<br /><em><%= l(:text_length_between, 2, 20) %> <%= l(:text_project_identifier_info) %></em> <br /><em><%= l(:text_length_between, 1, 20) %> <%= l(:text_project_identifier_info) %></em>
<% end %></p> <% end %></p>
<p><%= f.text_field :homepage, :size => 60 %></p> <p><%= f.text_field :homepage, :size => 60 %></p>
<p><%= f.check_box :is_public %></p> <p><%= f.check_box :is_public %></p>
+3 -1
View File
@@ -46,7 +46,9 @@
<% form_tag({}, :method => :get) do %> <% form_tag({}, :method => :get) do %>
<h3><%= l(:label_activity) %></h3> <h3><%= l(:label_activity) %></h3>
<p><% @activity.event_types.each do |t| %> <p><% @activity.event_types.each do |t| %>
<label><%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %> <%= l("label_#{t.singularize}_plural")%></label><br /> <%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %>
<%= link_to(l("label_#{t.singularize}_plural"), {"show_#{t}" => 1, :user_id => params[:user_id]})%>
<br />
<% end %></p> <% end %></p>
<% if @project && @project.active_children.any? %> <% if @project && @project.active_children.any? %>
<p><label><%= check_box_tag 'with_subprojects', 1, @with_subprojects %> <%=l(:label_subproject_plural)%></label></p> <p><label><%= check_box_tag 'with_subprojects', 1, @with_subprojects %> <%=l(:label_subproject_plural)%></label></p>
+12 -8
View File
@@ -6,7 +6,7 @@
<% delete_allowed = User.current.allowed_to?(:manage_files, @project) %> <% delete_allowed = User.current.allowed_to?(:manage_files, @project) %>
<table class="list"> <table class="list files">
<thead><tr> <thead><tr>
<%= sort_header_tag('filename', :caption => l(:field_filename)) %> <%= sort_header_tag('filename', :caption => l(:field_filename)) %>
<%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %> <%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %>
@@ -19,15 +19,19 @@
<% @containers.each do |container| %> <% @containers.each do |container| %>
<% next if container.attachments.empty? -%> <% next if container.attachments.empty? -%>
<% if container.is_a?(Version) -%> <% if container.is_a?(Version) -%>
<tr><th colspan="6" align="left"><span class="icon icon-package"><b><%=h container %></b></span></th></tr> <tr>
<th colspan="6" align="left">
<%= link_to(h(container), {:controller => 'versions', :action => 'show', :id => container}, :class => "icon icon-package") %>
</th>
</tr>
<% end -%> <% end -%>
<% container.attachments.each do |file| %> <% container.attachments.each do |file| %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="file <%= cycle("odd", "even") %>">
<td><%= link_to_attachment file, :download => true, :title => file.description %></td> <td class="filename"><%= link_to_attachment file, :download => true, :title => file.description %></td>
<td align="center"><%= format_time(file.created_on) %></td> <td class="created_on"><%= format_time(file.created_on) %></td>
<td align="center"><%= number_to_human_size(file.filesize) %></td> <td class="filesize"><%= number_to_human_size(file.filesize) %></td>
<td align="center"><%= file.downloads %></td> <td class="downloads"><%= file.downloads %></td>
<td align="center"><small><%= file.digest %></small></td> <td class="digest"><%= file.digest %></td>
<td align="center"> <td align="center">
<%= link_to(image_tag('delete.png'), {:controller => 'attachments', :action => 'destroy', :id => file}, <%= link_to(image_tag('delete.png'), {:controller => 'attachments', :action => 'destroy', :id => file},
:confirm => l(:text_are_you_sure), :method => :post) if delete_allowed %> :confirm => l(:text_are_you_sure), :method => :post) if delete_allowed %>
+5
View File
@@ -1,6 +1,8 @@
<h2><%=l(:label_settings)%></h2> <h2><%=l(:label_settings)%></h2>
<% tabs = project_settings_tabs %> <% tabs = project_settings_tabs %>
<% if tabs.any? %>
<% selected_tab = params[:tab] ? params[:tab].to_s : tabs.first[:name] %> <% selected_tab = params[:tab] ? params[:tab].to_s : tabs.first[:name] %>
<div class="tabs"> <div class="tabs">
@@ -20,5 +22,8 @@
:style => (tab[:name] != selected_tab ? 'display:none' : nil), :style => (tab[:name] != selected_tab ? 'display:none' : nil),
:class => 'tab-content') %> :class => 'tab-content') %>
<% end -%> <% end -%>
<% else %>
<p class="nodata"><%= l(:label_no_data) %></p>
<% end %>
<% html_title(l(:label_settings)) -%> <% html_title(l(:label_settings)) -%>
+1 -1
View File
@@ -14,7 +14,7 @@
<td><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></td> <td><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></td>
<td align="center"><%= format_date(version.effective_date) %></td> <td align="center"><%= format_date(version.effective_date) %></td>
<td><%=h version.description %></td> <td><%=h version.description %></td>
<td><%= link_to(version.wiki_page_title, :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td> <td><%= link_to(h(version.wiki_page_title), :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
<td align="center"><%= link_to_if_authorized l(:button_edit), { :controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %></td> <td align="center"><%= link_to_if_authorized l(:button_edit), { :controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %></td>
<td align="center"><%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></td> <td align="center"><%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></td>
</tr> </tr>
+3 -1
View File
@@ -11,7 +11,7 @@
<li><%=l(:field_parent)%>: <%= link_to h(@project.parent.name), :controller => 'projects', :action => 'show', :id => @project.parent %></li> <li><%=l(:field_parent)%>: <%= link_to h(@project.parent.name), :controller => 'projects', :action => 'show', :id => @project.parent %></li>
<% end %> <% end %>
<% @project.custom_values.each do |custom_value| %> <% @project.custom_values.each do |custom_value| %>
<% if !custom_value.value.empty? %> <% if !custom_value.value.blank? %>
<li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li> <li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
<% end %> <% end %>
<% end %> <% end %>
@@ -32,6 +32,7 @@
<p><%= link_to l(:label_issue_view_all), :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 %></p> <p><%= link_to l(:label_issue_view_all), :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 %></p>
</div> </div>
<% end %> <% end %>
<%= call_hook(:view_projects_show_left, :project => @project) %>
</div> </div>
<div class="splitcontentright"> <div class="splitcontentright">
@@ -53,6 +54,7 @@
<p><%= link_to l(:label_news_view_all), :controller => 'news', :action => 'index', :project_id => @project %></p> <p><%= link_to l(:label_news_view_all), :controller => 'news', :action => 'index', :project_id => @project %></p>
</div> </div>
<% end %> <% end %>
<%= call_hook(:view_projects_show_right, :project => @project) %>
</div> </div>
<% content_for :sidebar do %> <% content_for :sidebar do %>
@@ -1,7 +1,7 @@
<% @entries.each do |entry| %> <% @entries.each do |entry| %>
<% tr_id = Digest::MD5.hexdigest(entry.path) <% tr_id = Digest::MD5.hexdigest(entry.path)
depth = params[:depth].to_i %> depth = params[:depth].to_i %>
<tr id="<%= tr_id %>" class="<%= params[:parent_id] %> entry <%= entry.kind %>"> <tr id="<%= tr_id %>" class="<%= h params[:parent_id] %> entry <%= entry.kind %>">
<td style="padding-left: <%=18 * depth%>px;" class="filename"> <td style="padding-left: <%=18 * depth%>px;" class="filename">
<% if entry.is_dir? %> <% if entry.is_dir? %>
<span class="expander" onclick="<%= remote_function :url => {:action => 'browse', :id => @project, :path => to_path_param(entry.path), :rev => @rev, :depth => (depth + 1), :parent_id => tr_id}, <span class="expander" onclick="<%= remote_function :url => {:action => 'browse', :id => @project, :path => to_path_param(entry.path), :rev => @rev, :depth => (depth + 1), :parent_id => tr_id},
+1 -1
View File
@@ -11,7 +11,7 @@
<% syntax_highlight(@path, to_utf8(@annotate.content)).each_line do |line| %> <% syntax_highlight(@path, to_utf8(@annotate.content)).each_line do |line| %>
<% revision = @annotate.revisions[line_num-1] %> <% revision = @annotate.revisions[line_num-1] %>
<tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>"> <tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
<th class="line-num"><%= line_num %></th> <th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th>
<td class="revision"> <td class="revision">
<%= (revision.identifier ? link_to(format_revision(revision.identifier), :action => 'revision', :id => @project, :rev => revision.identifier) : format_revision(revision.revision)) if revision %></td> <%= (revision.identifier ? link_to(format_revision(revision.identifier), :action => 'revision', :id => @project, :rev => revision.identifier) : format_revision(revision.revision)) if revision %></td>
<td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td> <td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td>
+1 -1
View File
@@ -1,4 +1,4 @@
<h2><%=l(:label_role)%>: <%= @role.name %></h2> <h2><%=l(:label_role)%>: <%=h @role.name %></h2>
<% labelled_tabular_form_for :role, @role, :url => { :action => 'edit' }, :html => {:id => 'role_form'} do |f| %> <% labelled_tabular_form_for :role, @role, :url => { :action => 'edit' }, :html => {:id => 'role_form'} do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %> <%= render :partial => 'form', :locals => { :f => f } %>
+4 -4
View File
@@ -11,12 +11,12 @@
<%= text_field_tag 'settings[issues_export_limit]', Setting.issues_export_limit, :size => 6 %></p> <%= text_field_tag 'settings[issues_export_limit]', Setting.issues_export_limit, :size => 6 %></p>
</div> </div>
<fieldset class="box"><legend><%= l(:setting_issue_list_default_columns) %></legend> <fieldset class="box settings"><legend><%= l(:setting_issue_list_default_columns) %></legend>
<%= hidden_field_tag 'settings[issue_list_default_columns][]', '' %> <%= hidden_field_tag 'settings[issue_list_default_columns][]', '' %>
<p><% Query.new.available_columns.each do |column| %> <% Query.new.available_columns.each do |column| %>
<label><%= check_box_tag 'settings[issue_list_default_columns][]', column.name, Setting.issue_list_default_columns.include?(column.name.to_s) %> <label><%= check_box_tag 'settings[issue_list_default_columns][]', column.name, Setting.issue_list_default_columns.include?(column.name.to_s) %>
<%= column.caption %></label> <%= column.caption %></label><br />
<% end %></p> <% end %>
</fieldset> </fieldset>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
+1 -1
View File
@@ -7,7 +7,7 @@
<h2><%= l(:label_spent_time) %></h2> <h2><%= l(:label_spent_time) %></h2>
<% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %> <% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %>
<%= hidden_field_tag 'project_id', params[:project_id] %> <%= hidden_field_tag('project_id', params[:project_id]) if @project %>
<%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %> <%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %>
<%= render :partial => 'date_range' %> <%= render :partial => 'date_range' %>
<% end %> <% end %>
+1 -1
View File
@@ -10,7 +10,7 @@
<% @criterias.each do |criteria| %> <% @criterias.each do |criteria| %>
<%= hidden_field_tag 'criterias[]', criteria, :id => nil %> <%= hidden_field_tag 'criterias[]', criteria, :id => nil %>
<% end %> <% end %>
<%= hidden_field_tag 'project_id', params[:project_id] %> <%= hidden_field_tag('project_id', params[:project_id]) if @project %>
<%= render :partial => 'date_range' %> <%= render :partial => 'date_range' %>
<p><%= l(:label_details) %>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'], <p><%= l(:label_details) %>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
+1
View File
@@ -13,6 +13,7 @@
<% end %> <% end %>
<p><%= f.check_box :admin, :disabled => (@user == User.current) %></p> <p><%= f.check_box :admin, :disabled => (@user == User.current) %></p>
<%= call_hook(:view_users_form, :user => @user, :form => f) %>
</div> </div>
<div class="box"> <div class="box">
+2
View File
@@ -4,6 +4,7 @@
<th><%= l(:label_project) %></th> <th><%= l(:label_project) %></th>
<th><%= l(:label_role) %></th> <th><%= l(:label_role) %></th>
<th style="width:15%"></th> <th style="width:15%"></th>
<%= call_hook(:view_users_memberships_table_header, :user => @user )%>
</thead> </thead>
<tbody> <tbody>
<% @memberships.each do |membership| %> <% @memberships.each do |membership| %>
@@ -19,6 +20,7 @@
<td align="center"> <td align="center">
<%= link_to l(:button_delete), {:action => 'destroy_membership', :id => @user, :membership_id => membership }, :method => :post, :class => 'icon icon-del' %> <%= link_to l(:button_delete), {:action => 'destroy_membership', :id => @user, :membership_id => membership }, :method => :post, :class => 'icon icon-del' %>
</td> </td>
<%= call_hook(:view_users_memberships_table_row, :user => @user, :membership => membership, :roles => @roles, :projects => @projects )%>
</tr> </tr>
</tbody> </tbody>
<% end; reset_cycle %> <% end; reset_cycle %>
+1
View File
@@ -1,5 +1,6 @@
<div class="contextual"> <div class="contextual">
<%= link_to_if_authorized l(:button_edit), {:controller => 'versions', :action => 'edit', :id => @version}, :class => 'icon icon-edit' %> <%= link_to_if_authorized l(:button_edit), {:controller => 'versions', :action => 'edit', :id => @version}, :class => 'icon icon-edit' %>
<%= call_hook(:view_versions_show_contextual, { :version => @version, :project => @project }) %>
</div> </div>
<h2><%= h(@version.name) %></h2> <h2><%= h(@version.name) %></h2>
+2
View File
@@ -9,6 +9,7 @@
<%= link_to l(:label_news_view_all), :controller => 'news' %> <%= link_to l(:label_news_view_all), :controller => 'news' %>
</div> </div>
<% end %> <% end %>
<%= call_hook(:view_welcome_index_left, :projects => @projects) %>
</div> </div>
<div class="splitcontentright"> <div class="splitcontentright">
@@ -25,6 +26,7 @@
</ul> </ul>
</div> </div>
<% end %> <% end %>
<%= call_hook(:view_welcome_index_right, :projects => @projects) %>
</div> </div>
<% content_for :header_tags do %> <% content_for :header_tags do %>
+3
View File
@@ -10,6 +10,9 @@ ul.toc { padding: 4px; margin-left: 0; }
ul.toc li { list-style-type:none; } ul.toc li { list-style-type:none; }
ul.toc li.heading2 { margin-left: 1em; } ul.toc li.heading2 { margin-left: 1em; }
ul.toc li.heading3 { margin-left: 2em; } ul.toc li.heading3 { margin-left: 2em; }
a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; }
a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; }
h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; }
</style> </style>
</head> </head>
<body> <body>
+7
View File
@@ -6,6 +6,13 @@
<style> <style>
body { font:80% Verdana,Tahoma,Arial,sans-serif; } body { font:80% Verdana,Tahoma,Arial,sans-serif; }
h1, h2, h3, h4 { font-family: "Trebuchet MS",Georgia,"Times New Roman",serif; } h1, h2, h3, h4 { font-family: "Trebuchet MS",Georgia,"Times New Roman",serif; }
ul.toc { padding: 4px; margin-left: 0; }
ul.toc li { list-style-type:none; }
ul.toc li.heading2 { margin-left: 1em; }
ul.toc li.heading3 { margin-left: 2em; }
a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; }
a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; }
h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; }
</style> </style>
</head> </head>
<body> <body>
+2
View File
@@ -31,6 +31,7 @@
<%= link_to_attachments @page %> <%= link_to_attachments @page %>
<% if @editable && authorize_for('wiki', 'add_attachment') %> <% if @editable && authorize_for('wiki', 'add_attachment') %>
<div id="wiki_add_attachment">
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;", <p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
:id => 'attach_files_link' %></p> :id => 'attach_files_link' %></p>
<% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %> <% form_tag({ :controller => 'wiki', :action => 'add_attachment', :page => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
@@ -40,6 +41,7 @@
<%= submit_tag l(:button_add) %> <%= submit_tag l(:button_add) %>
<%= link_to l(:button_cancel), {}, :onclick => "Element.hide('add_attachment_form'); Element.show('attach_files_link'); return false;" %> <%= link_to l(:button_cancel), {}, :onclick => "Element.hide('add_attachment_form'); Element.show('attach_files_link'); return false;" %>
<% end %> <% end %>
</div>
<% end %> <% end %>
<p class="other-formats"> <p class="other-formats">
+2 -2
View File
@@ -20,11 +20,11 @@
<% unless @pages.empty? %> <% unless @pages.empty? %>
<p class="other-formats"> <p class="other-formats">
<%= l(:label_export_to) %> <%= l(:label_export_to) %>
<span><%= link_to 'Atom', {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span> <span><%= link_to 'Atom', {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_edits => 1, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
<span><%= link_to 'HTML', {:action => 'special', :page => 'export'}, :class => 'html' %></span> <span><%= link_to 'HTML', {:action => 'special', :page => 'export'}, :class => 'html' %></span>
</p> </p>
<% end %> <% end %>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key) %> <%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_edits => 1, :format => 'atom', :key => User.current.rss_key) %>
<% end %> <% end %>
+2 -2
View File
@@ -13,11 +13,11 @@
<% unless @pages.empty? %> <% unless @pages.empty? %>
<p class="other-formats"> <p class="other-formats">
<%= l(:label_export_to) %> <%= l(:label_export_to) %>
<span><%= link_to 'Atom', {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span> <span><%= link_to 'Atom', {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_edits => 1, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
<span><%= link_to 'HTML', {:action => 'special', :page => 'export'} %></span> <span><%= link_to 'HTML', {:action => 'special', :page => 'export'} %></span>
</p> </p>
<% end %> <% end %>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key) %> <%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_edits => 1, :format => 'atom', :key => User.current.rss_key) %>
<% end %> <% end %>
+3
View File
@@ -15,3 +15,6 @@ config.action_controller.perform_caching = false
config.action_mailer.perform_deliveries = true config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :test config.action_mailer.delivery_method = :test
# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
config.action_controller.allow_forgery_protection = false
+4
View File
@@ -15,3 +15,7 @@ config.action_controller.perform_caching = false
config.action_mailer.perform_deliveries = true config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :test config.action_mailer.delivery_method = :test
# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
config.action_controller.allow_forgery_protection = false
+3
View File
@@ -15,3 +15,6 @@ config.action_controller.perform_caching = false
config.action_mailer.perform_deliveries = true config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :test config.action_mailer.delivery_method = :test
# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
config.action_controller.allow_forgery_protection = false
@@ -0,0 +1,30 @@
# Copyright (c) 2009 Michael Koziarski <michael@koziarski.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
require 'bigdecimal'
alias BigDecimalUnsafe BigDecimal
# This fixes CVE-2009-1904 however it removes legitimate functionality that your
# application may depend on. You are *strongly* advised to upgrade your ruby
# rather than relying on this fix for an extended period of time.
def BigDecimal(initial, digits=0)
if initial.size > 255 || initial =~ /e/i
raise "Invalid big Decimal Value"
end
BigDecimalUnsafe(initial, digits)
end
+90
View File
@@ -4,6 +4,96 @@ Redmine - project management software
Copyright (C) 2006-2009 Jean-Philippe Lang Copyright (C) 2006-2009 Jean-Philippe Lang
http://www.redmine.org/ http://www.redmine.org/
== 2009-11-15 v0.8.7
* Fixed: Hide paragraph terminator at the end of headings on html export
* Fixed: pre tags containing "<pre*"
* Fixed: First date of the date range not included in the time report with SQLite
* Fixed: Password field not styled correctly on alternative stylesheet
* Fixed: Error when sumbitting a POST request that requires a login
* Fixed: CSRF vulnerabilities
== 2009-11-04 v0.8.6
* Change links to closed issues to be a grey color
* Change subversion adapter to not cache authentication and run non interactively
* Fixed: Custom Values with a nil value cause HTTP error 500
* Fixed: Failure to convert HTML entities when editing an Issue reply
* Fixed: Error trying to show repository when there are no comments in a changeset
* Fixed: account/show/:user_id should not be accessible for other users not in your projects
* Fixed: XSS vulnerabilities
* Fixed: IssuesController#destroy should accept POST only
* Fixed: Inline images in wiki headings
== 2009-09-13 v0.8.5
* Incoming mail handler : Allow spaces between keywords and colon
* Do not require a non-word character after a comma in Redmine links
* Include issue hyperlinks in reminder emails
* Prevent nil error when retrieving svn version
* Various plugin hooks added
* Add plugins information to script/about
* Fixed: 500 Internal Server Error is raised if add an empty comment to the news
* Fixed: Atom links for wiki pages are not correct
* Fixed: Atom feeds leak email address
* Fixed: Case sensitivity in Issue filtering
* Fixed: When reading RSS feed, the inline-embedded images are not properly shown
== 2009-05-17 v0.8.4
* Allow textile mailto links
* Fixed: memory consumption when uploading file
* Fixed: Mercurial integration doesn't work if Redmine is installed in folder path containing space
* Fixed: an error is raised when no tab is available on project settings
* Fixed: insert image macro corrupts urls with excalamation marks
* Fixed: error on cross-project gantt PNG export
* Fixed: self and alternate links in atom feeds do not respect Atom specs
* Fixed: accept any svn tunnel scheme in repository URL
* Fixed: issues/show should accept user's rss key
* Fixed: consistency of custom fields display on the issue detail view
* Fixed: wiki comments length validation is missing
* Fixed: weak autologin token generation algorithm causes duplicate tokens
== 2009-04-05 v0.8.3
* Separate project field and subject in cross-project issue view
* Ability to set language for redmine:load_default_data task using REDMINE_LANG environment variable
* Rescue Redmine::DefaultData::DataAlreadyLoaded in redmine:load_default_data task
* CSS classes to highlight own and assigned issues
* Hide "New file" link on wiki pages from printing
* Flush buffer when asking for language in redmine:load_default_data task
* Minimum project identifier length set to 1
* Include headers so that emails don't trigger vacation auto-responders
* Fixed: Time entries csv export links for all projects are malformed
* Fixed: Files without Version aren't visible in the Activity page
* Fixed: Commit logs are centered in the repo browser
* Fixed: News summary field content is not searchable
* Fixed: Journal#save has a wrong signature
* Fixed: Email footer signature convention
* Fixed: Timelog report do not show time for non-versioned issues
== 2009-03-07 v0.8.2
* Send an email to the user when an administrator activates a registered user
* Strip keywords from received email body
* Footer updated to 2009
* Show RSS-link even when no issues is found
* One click filter action in activity view
* Clickable/linkable line #'s while browsing the repo or viewing a file
* Links to versions on files list
* Added request and controller objects to the hooks by default
* Fixed: exporting an issue with attachments to PDF raises an error
* Fixed: "too few arguments" error may occur on activerecord error translation
* Fixed: "Default columns Displayed on the Issues list" setting is not easy to read
* Fixed: visited links to closed tickets are not striked through with IE6
* Fixed: MailHandler#plain_text_body returns nil if there was nothing to strip
* Fixed: MailHandler raises an error when processing an email without From header
== 2009-02-15 v0.8.1 == 2009-02-15 v0.8.1
+6 -3
View File
@@ -30,7 +30,10 @@ Optional:
rake db:migrate RAILS_ENV="production" rake db:migrate RAILS_ENV="production"
It will create tables and an administrator account. It will create tables and an administrator account.
5. Setting up permissions 5. Generate a session store secret. Run:
rake config/initializers/session_store.rb
6. Setting up permissions
The user who runs Redmine must have write permission on the following The user who runs Redmine must have write permission on the following
subdirectories: files, log, tmp (create the last one if not present). subdirectories: files, log, tmp (create the last one if not present).
@@ -39,13 +42,13 @@ Optional:
sudo chown -R redmine:redmine files log tmp sudo chown -R redmine:redmine files log tmp
sudo chmod -R 755 files log tmp sudo chmod -R 755 files log tmp
6. Test the installation by running WEBrick web server: 7. Test the installation by running WEBrick web server:
ruby script/server -e production ruby script/server -e production
Once WEBrick has started, point your browser to http://localhost:3000/ Once WEBrick has started, point your browser to http://localhost:3000/
You should now see the application welcome page You should now see the application welcome page
7. Use default administrator account to log in: 8. Use default administrator account to log in:
login: admin login: admin
password: admin password: admin
+3 -3
View File
@@ -681,6 +681,6 @@ text_user_mail_option: "De los proyectos no seleccionados, sólo recibirá notif
text_user_wrote: '%s escribió:' text_user_wrote: '%s escribió:'
text_wiki_destroy_confirmation: ¿Seguro que quiere borrar el wiki y todo su contenido? text_wiki_destroy_confirmation: ¿Seguro que quiere borrar el wiki y todo su contenido?
text_workflow_edit: Seleccionar un flujo de trabajo para actualizar text_workflow_edit: Seleccionar un flujo de trabajo para actualizar
text_plugin_assets_writable: Plugin assets directory writable text_plugin_assets_writable: Se puede escribir en el directorio de extensiones activas
warning_attachments_not_saved: "%d file(s) could not be saved." warning_attachments_not_saved: "No pudieron guardarse %d fichero(s)."
button_create_and_continue: Create and continue button_create_and_continue: Crear y continuar
+3 -3
View File
@@ -792,7 +792,7 @@ class RedCloth3 < String
(?:\(([^)]+?)\)(?="))? # $title (?:\(([^)]+?)\)(?="))? # $title
": ":
( # $url ( # $url
(\/|[a-zA-Z]+:\/\/|www\.) # $proto (\/|[a-zA-Z]+:\/\/|www\.|mailto:) # $proto
[\w\/]\S+? [\w\/]\S+?
) )
(\/)? # $slash (\/)? # $slash
@@ -907,7 +907,7 @@ class RedCloth3 < String
end end
IMAGE_RE = / IMAGE_RE = /
(<p>|.|^) # start of line? (>|\s|^) # start of line?
\! # opening \! # opening
(\<|\=|\>)? # optional alignment atts (\<|\=|\>)? # optional alignment atts
(#{C}) # optional style,class atts (#{C}) # optional style,class atts
@@ -1011,7 +1011,7 @@ class RedCloth3 < String
end end
OFFTAGS = /(code|pre|kbd|notextile)/ OFFTAGS = /(code|pre|kbd|notextile)/
OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }|\Z)/mi OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\W|\Z)/mi
OFFTAG_OPEN = /<#{ OFFTAGS }/ OFFTAG_OPEN = /<#{ OFFTAGS }/
OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/ OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
+16
View File
@@ -0,0 +1,16 @@
module Redmine
class About
def self.print_plugin_info
plugins = Redmine::Plugin.registered_plugins
if !plugins.empty?
column_with = plugins.map {|internal_name, plugin| plugin.name.length}.max
puts "\nAbout your Redmine plugins"
plugins.each do |internal_name, plugin|
puts sprintf("%-#{column_with}s %s", plugin.name, plugin.version)
end
end
end
end
end
+2
View File
@@ -21,6 +21,8 @@ require 'rfpdf/chinese'
module Redmine module Redmine
module Export module Export
module PDF module PDF
include ActionView::Helpers::NumberHelper
class IFPDF < FPDF class IFPDF < FPDF
include GLoc include GLoc
attr_accessor :footer_date attr_accessor :footer_date
+50 -9
View File
@@ -17,6 +17,8 @@
module Redmine module Redmine
module Hook module Hook
include ActionController::UrlWriter
@@listener_classes = [] @@listener_classes = []
@@listeners = nil @@listeners = nil
@@hook_listeners = {} @@hook_listeners = {}
@@ -55,11 +57,12 @@ module Redmine
# Calls a hook. # Calls a hook.
# Returns the listeners response. # Returns the listeners response.
def call_hook(hook, context={}) def call_hook(hook, context={})
response = '' returning [] do |response|
hook_listeners(hook).each do |listener| hls = hook_listeners(hook)
response << listener.send(hook, context).to_s if hls.any?
hls.each {|listener| response << listener.send(hook, context)}
end
end end
response
end end
end end
@@ -73,8 +76,9 @@ module Redmine
Redmine::Hook.add_listener(child) Redmine::Hook.add_listener(child)
super super
end end
end end
# Listener class used for views hooks. # Listener class used for views hooks.
# Listeners that inherit this class will include various helpers by default. # Listeners that inherit this class will include various helpers by default.
class ViewListener < Listener class ViewListener < Listener
@@ -91,17 +95,54 @@ module Redmine
include ActionView::Helpers::TextHelper include ActionView::Helpers::TextHelper
include ActionController::UrlWriter include ActionController::UrlWriter
include ApplicationHelper include ApplicationHelper
# Default to creating links using only the path. Subclasses can
# change this default as needed
def self.default_url_options
{:only_path => true }
end
# Helper method to directly render a partial using the context:
#
# class MyHook < Redmine::Hook::ViewListener
# render_on :view_issues_show_details_bottom, :partial => "show_more_data"
# end
#
def self.render_on(hook, options={})
define_method hook do |context|
context[:controller].send(:render_to_string, {:locals => context}.merge(options))
end
end
end end
# Helper module included in ApplicationHelper so that hooks can be called # Helper module included in ApplicationHelper and ActionControllerso that
# in views like this: # hooks can be called in views like this:
#
# <%= call_hook(:some_hook) %> # <%= call_hook(:some_hook) %>
# <%= call_hook(:another_hook, :foo => 'bar' %> # <%= call_hook(:another_hook, :foo => 'bar' %>
# #
# Current project is automatically added to the call context. # Or in controllers like:
# call_hook(:some_hook)
# call_hook(:another_hook, :foo => 'bar'
#
# Hooks added to views will be concatenated into a string. Hooks added to
# controllers will return an array of results.
#
# Several objects are automatically added to the call context:
#
# * project => current project
# * request => Request instance
# * controller => current Controller instance
#
module Helper module Helper
def call_hook(hook, context={}) def call_hook(hook, context={})
Redmine::Hook.call_hook(hook, {:project => @project}.merge(context)) if is_a?(ActionController::Base)
default_context = {:controller => self, :project => @project, :request => request}
Redmine::Hook.call_hook(hook, default_context.merge(context))
else
default_context = {:controller => controller, :project => @project, :request => request}
Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ')
end
end end
end end
end end
@@ -105,7 +105,7 @@ module Redmine
# makes Mercurial produce a xml output. # makes Mercurial produce a xml output.
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
revisions = Revisions.new revisions = Revisions.new
cmd = "#{HG_BIN} --debug --encoding utf8 -R #{target('')} log -C --style #{self.class.template_path}" cmd = "#{HG_BIN} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}"
if identifier_from && identifier_to if identifier_from && identifier_to
cmd << " -r #{identifier_from.to_i}:#{identifier_to.to_i}" cmd << " -r #{identifier_from.to_i}:#{identifier_to.to_i}"
elsif identifier_from elsif identifier_from
@@ -37,7 +37,7 @@ module Redmine
version = nil version = nil
shellout(cmd) do |io| shellout(cmd) do |io|
# Read svn version in first returned line # Read svn version in first returned line
if m = io.gets.match(%r{((\d+\.)+\d+)}) if m = io.gets.to_s.match(%r{((\d+\.)+\d+)})
version = m[0].scan(%r{\d+}).collect(&:to_i) version = m[0].scan(%r{\d+}).collect(&:to_i)
end end
end end
@@ -224,6 +224,7 @@ module Redmine
str = '' str = ''
str << " --username #{shell_quote(@login)}" unless @login.blank? str << " --username #{shell_quote(@login)}" unless @login.blank?
str << " --password #{shell_quote(@password)}" unless @login.blank? || @password.blank? str << " --password #{shell_quote(@password)}" unless @login.blank? || @password.blank?
str << " --no-auth-cache --non-interactive"
str str
end end
end end
+38
View File
@@ -0,0 +1,38 @@
# Redmine - project management software
# Copyright (C) 2006-2009 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 Redmine
module Utils
class << self
# Returns the relative root url of the application
def relative_url_root
ActionController::Base.respond_to?('relative_url_root') ?
ActionController::Base.relative_url_root.to_s :
ActionController::AbstractRequest.relative_url_root.to_s
end
# Sets the relative root url of the application
def relative_url_root=(arg)
if ActionController::Base.respond_to?('relative_url_root=')
ActionController::Base.relative_url_root=arg
else
ActionController::AbstractRequest.relative_url_root=arg
end
end
end
end
end
+1 -1
View File
@@ -4,7 +4,7 @@ module Redmine
module VERSION #:nodoc: module VERSION #:nodoc:
MAJOR = 0 MAJOR = 0
MINOR = 8 MINOR = 8
TINY = 1 TINY = 7
# Branch values: # Branch values:
# * official release: nil # * official release: nil
+24
View File
@@ -0,0 +1,24 @@
desc 'Generates a configuration file for cookie store sessions.'
file 'config/initializers/session_store.rb' do
path = File.join(RAILS_ROOT, 'config', 'initializers', 'session_store.rb')
secret = Rails::SecretKeyGenerator.new(self).generate_secret[0,40]
File.open(path, 'w') do |f|
f.write <<"EOF"
# This file was generated by 'rake config/initializers/session_store.rb',
# and should not be made visible to public.
# If you have a load-balancing Redmine cluster, you will need to use the
# same version of this file on each machine. And be sure to restart your
# server when you modify this file.
# Your secret key for verifying cookie session data integrity. If you
# change this key, all old sessions will become invalid! Make sure the
# secret is at least 30 characters and all random, no regular words or
# you'll be exposed to dictionary attacks.
ActionController::Base.session = {
:session_key => '_redmine_session',
:secret => '#{secret}'
}
EOF
end
end
+18 -12
View File
@@ -1,26 +1,32 @@
desc 'Load Redmine default configuration data' desc 'Load Redmine default configuration data. Language is chosen interactively or by setting REDMINE_LANG environment variable.'
namespace :redmine do namespace :redmine do
task :load_default_data => :environment do task :load_default_data => :environment do
include GLoc include GLoc
set_language_if_valid('en') set_language_if_valid('en')
puts
while true envlang = ENV['REDMINE_LANG']
print "Select language: " if !envlang || !set_language_if_valid(envlang)
print GLoc.valid_languages.sort {|x,y| x.to_s <=> y.to_s }.join(", ") puts
print " [#{GLoc.current_language}] " while true
lang = STDIN.gets.chomp! print "Select language: "
break if lang.empty? print GLoc.valid_languages.sort {|x,y| x.to_s <=> y.to_s }.join(", ")
break if set_language_if_valid(lang) print " [#{GLoc.current_language}] "
puts "Unknown language!" STDOUT.flush
lang = STDIN.gets.chomp!
break if lang.empty?
break if set_language_if_valid(lang)
puts "Unknown language!"
end
STDOUT.flush
puts "===================================="
end end
puts "===================================="
begin begin
Redmine::DefaultData::Loader.load(current_language) Redmine::DefaultData::Loader.load(current_language)
puts "Default configuration data loaded." puts "Default configuration data loaded."
rescue Redmine::DefaultData::DataAlreadyLoaded => error
puts error
rescue => error rescue => error
puts "Error: " + error puts "Error: " + error
puts "Default configuration data was not loaded." puts "Default configuration data was not loaded."
+7 -2
View File
@@ -195,8 +195,13 @@ task :migrate_from_mantis => :environment do
file_type file_type
end end
def read def read(*args)
content if @read_finished
nil
else
@read_finished = true
content
end
end end
end end
+25 -14
View File
@@ -135,8 +135,15 @@ namespace :redmine do
File.file? trac_fullpath File.file? trac_fullpath
end end
def read def open
File.open("#{trac_fullpath}", 'rb').read File.open("#{trac_fullpath}", 'rb') {|f|
@file = f
yield self
}
end
def read(*args)
@file.read(*args)
end end
def description def description
@@ -506,12 +513,14 @@ namespace :redmine do
# Attachments # Attachments
ticket.attachments.each do |attachment| ticket.attachments.each do |attachment|
next unless attachment.exist? next unless attachment.exist?
a = Attachment.new :created_on => attachment.time attachment.open {
a.file = attachment a = Attachment.new :created_on => attachment.time
a.author = find_or_create_user(attachment.author) a.file = attachment
a.container = i a.author = find_or_create_user(attachment.author)
a.description = attachment.description a.container = i
migrated_ticket_attachments += 1 if a.save a.description = attachment.description
migrated_ticket_attachments += 1 if a.save
}
end end
# Custom fields # Custom fields
@@ -556,12 +565,14 @@ namespace :redmine do
page.attachments.each do |attachment| page.attachments.each do |attachment|
next unless attachment.exist? next unless attachment.exist?
next if p.attachments.find_by_filename(attachment.filename.gsub(/^.*(\\|\/)/, '').gsub(/[^\w\.\-]/,'_')) #add only once per page next if p.attachments.find_by_filename(attachment.filename.gsub(/^.*(\\|\/)/, '').gsub(/[^\w\.\-]/,'_')) #add only once per page
a = Attachment.new :created_on => attachment.time attachment.open {
a.file = attachment a = Attachment.new :created_on => attachment.time
a.author = find_or_create_user(attachment.author) a.file = attachment
a.description = attachment.description a.author = find_or_create_user(attachment.author)
a.container = p a.description = attachment.description
migrated_wiki_attachments += 1 if a.save a.container = p
migrated_wiki_attachments += 1 if a.save
}
end end
end end
+2 -1
View File
@@ -69,7 +69,8 @@ function setPredecessorFieldsVisibility() {
function promptToRemote(text, param, url) { function promptToRemote(text, param, url) {
value = prompt(text + ':'); value = prompt(text + ':');
if (value) { if (value) {
new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true}); var sep = (url.indexOf('?') < 0 ? '?' : '&' )
new Ajax.Request(url + sep + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
return false; return false;
} }
} }
+7 -2
View File
@@ -18,7 +18,7 @@ h4, .wiki h3 {font-size: 13px;padding: 2px 10px 1px 0px;margin-bottom: 5px; bord
padding: 0px 0px 0px 0px; padding: 0px 0px 0px 0px;
white-space:nowrap; white-space:nowrap;
} }
#top-menu a {color: #fff; padding-right: 8px; font-weight: bold;} #top-menu a {color: #fff; margin-right: 8px; font-weight: bold;}
#top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; } #top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; }
#account {float:right;} #account {float:right;}
@@ -76,7 +76,7 @@ a, a:link, a:visited{ color: #2A5685; text-decoration: none; }
a:hover, a:active{ color: #c61a1a; text-decoration: underline;} a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
a img{ border: 0; } a img{ border: 0; }
a.issue.closed { text-decoration: line-through; } a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; }
/***** Tables *****/ /***** Tables *****/
table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; } table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
@@ -104,6 +104,10 @@ tr.entry.file td.filename a { margin-left: 16px; }
tr.changeset td.author { text-align: center; width: 15%; } tr.changeset td.author { text-align: center; width: 15%; }
tr.changeset td.committed_on { text-align: center; width: 15%; } tr.changeset td.committed_on { text-align: center; width: 15%; }
table.files tr.file td { text-align: center; }
table.files tr.file td.filename { text-align: left; padding-left: 24px; }
table.files tr.file td.digest { font-size: 80%; }
tr.message { height: 2.6em; } tr.message { height: 2.6em; }
tr.message td.last_message { font-size: 80%; } tr.message td.last_message { font-size: 80%; }
tr.message.locked td.subject a { background-image: url(../images/locked.png); } tr.message.locked td.subject a { background-image: url(../images/locked.png); }
@@ -679,4 +683,5 @@ h2 img { vertical-align:middle; }
#top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; } #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; }
#main { background: #fff; } #main { background: #fff; }
#content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;} #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;}
#wiki_add_attachment { display:none; }
} }
+4
View File
@@ -40,6 +40,10 @@ table.filecontent th.line-num {
padding-right: 3px; padding-right: 3px;
color: #999; color: #999;
} }
table.filecontent th.line-num a {
text-decoration: none;
color: inherit;
}
table.filecontent td.line-code pre { table.filecontent td.line-code pre {
white-space: pre-wrap; /* CSS2.1 compliant */ white-space: pre-wrap; /* CSS2.1 compliant */
white-space: -moz-pre-wrap; /* Mozilla-based browsers */ white-space: -moz-pre-wrap; /* Mozilla-based browsers */
@@ -61,9 +61,9 @@ input[type="button"], input[type="submit"], input[type="reset"] { background-col
input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { background-color: #ccccbb; } input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { background-color: #ccccbb; }
/* Fields */ /* Fields */
input[type="text"], textarea, select { padding: 2px; border: 1px solid #d7d7d7; } input[type="text"], input[type="password"], textarea, select { padding: 2px; border: 1px solid #d7d7d7; }
input[type="text"] { padding: 3px; } input[type="text"], input[type="password"] { padding: 3px; }
input[type="text"]:focus, textarea:focus, select:focus { border: 1px solid #888866; } input[type="text"]:focus, input[type="password"]:focus, textarea:focus, select:focus { border: 1px solid #888866; }
option { border-bottom: 1px dotted #d7d7d7; } option { border-bottom: 1px dotted #d7d7d7; }
/* Misc */ /* Misc */
+4 -1
View File
@@ -1,3 +1,6 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot' require File.dirname(__FILE__) + '/../config/boot'
require 'commands/about' $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info"
require 'commands/about'
Redmine::About.print_plugin_info
+12
View File
@@ -109,4 +109,16 @@ attachments_009:
filename: version_file.zip filename: version_file.zip
author_id: 2 author_id: 2
content_type: application/octet-stream content_type: application/octet-stream
attachments_010:
created_on: 2006-07-19 21:07:27 +02:00
container_type: Issue
container_id: 2
downloads: 0
disk_filename: 060719210727_picture.jpg
digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
id: 10
filesize: 452
filename: picture.jpg
author_id: 2
content_type: image/jpeg
+7
View File
@@ -13,4 +13,11 @@ journals_002:
journalized_type: Issue journalized_type: Issue
user_id: 2 user_id: 2
journalized_id: 1 journalized_id: 1
journals_003:
created_on: <%= 1.days.ago.to_date.to_s(:db) %>
notes: "A comment with inline image: !picture.jpg!"
id: 3
journalized_type: Issue
user_id: 2
journalized_id: 2
@@ -0,0 +1,43 @@
Return-Path: <jsmith@somenet.foo>
Received: from osiris ([127.0.0.1])
by OSIRIS
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
From: "John Smith" <jsmith@somenet.foo>
To: <redmine@somenet.foo>
Subject: New ticket on a given project
Date: Sun, 22 Jun 2008 12:28:07 +0200
MIME-Version: 1.0
Content-Type: text/plain;
format=flowed;
charset="iso-8859-1";
reply-type=original
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique
sed, mauris. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse
platea dictumst.
Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque
sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem.
Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et,
dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed,
massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo
pulvinar dui, a gravida orci mi eget odio. Nunc a lacus.
Project : onlinestore
Tracker: Feature request
category : Stock management
priority: Urgent
@@ -0,0 +1,40 @@
Received: from osiris ([127.0.0.1])
by OSIRIS
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
To: <redmine@somenet.foo>
Subject: New ticket on a given project
Date: Sun, 22 Jun 2008 12:28:07 +0200
MIME-Version: 1.0
Content-Type: text/plain;
format=flowed;
charset="iso-8859-1";
reply-type=original
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique
sed, mauris. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse
platea dictumst.
Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque
sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem.
Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et,
dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed,
massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo
pulvinar dui, a gravida orci mi eget odio. Nunc a lacus.
Project: onlinestore
Status: Resolved
+48
View File
@@ -96,5 +96,53 @@ users_006:
mail_notification: false mail_notification: false
login: '' login: ''
type: AnonymousUser type: AnonymousUser
users_007:
id: 7
created_on: 2006-07-19 19:33:19 +02:00
status: 1
last_login_on:
language: ''
hashed_password: 1
updated_on: 2006-07-19 19:33:19 +02:00
admin: false
mail: someone@foo.bar
lastname: One
firstname: Some
auth_source_id:
mail_notification: false
login: someone
type: User
users_008:
id: 8
created_on: 2006-07-19 19:33:19 +02:00
status: 1
last_login_on:
language: 'it'
hashed_password: 1
updated_on: 2006-07-19 19:33:19 +02:00
admin: false
mail: miscuser8@foo.bar
lastname: Misc
firstname: User
auth_source_id:
mail_notification: false
login: miscuser8
type: User
users_009:
id: 9
created_on: 2006-07-19 19:33:19 +02:00
status: 1
last_login_on:
language: 'it'
hashed_password: 1
updated_on: 2006-07-19 19:33:19 +02:00
admin: false
mail: miscuser9@foo.bar
lastname: Misc
firstname: User
auth_source_id:
mail_notification: false
login: miscuser9
type: User
@@ -37,13 +37,30 @@ class AccountControllerTest < Test::Unit::TestCase
assert_template 'show' assert_template 'show'
assert_not_nil assigns(:user) assert_not_nil assigns(:user)
end end
def test_show_should_not_fail_when_custom_values_are_nil
user = User.find(2)
# Create a custom field to illustrate the issue
custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
custom_value = user.custom_values.build(:custom_field => custom_field).save!
get :show, :id => 2
assert_response :success
end
def test_show_inactive def test_show_inactive
get :show, :id => 5 get :show, :id => 5
assert_response 404 assert_response 404
assert_nil assigns(:user) assert_nil assigns(:user)
end end
def test_show_should_not_reveal_users_with_no_visible_activity_or_project
get :show, :id => 9
assert_response 404
end
def test_login_should_redirect_to_back_url_param def test_login_should_redirect_to_back_url_param
# request.uri is "test.host" in test environment # request.uri is "test.host" in test environment
post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.host%2Fissues%2Fshow%2F1' post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.host%2Fissues%2Fshow%2F1'
+13 -1
View File
@@ -51,6 +51,8 @@ class IssuesControllerTest < Test::Unit::TestCase
end end
def test_index def test_index
Setting.default_language = 'en'
get :index get :index
assert_response :success assert_response :success
assert_template 'index.rhtml' assert_template 'index.rhtml'
@@ -61,6 +63,8 @@ class IssuesControllerTest < Test::Unit::TestCase
# private projects hidden # private projects hidden
assert_no_tag :tag => 'a', :content => /Issue of a private subproject/ assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
assert_no_tag :tag => 'a', :content => /Issue on project 2/ assert_no_tag :tag => 'a', :content => /Issue on project 2/
# project column
assert_tag :tag => 'th', :content => /Project/
end end
def test_index_should_not_list_issues_when_module_disabled def test_index_should_not_list_issues_when_module_disabled
@@ -251,9 +255,17 @@ class IssuesControllerTest < Test::Unit::TestCase
:child => { :tag => 'legend', :child => { :tag => 'legend',
:content => /Notes/ } } :content => /Notes/ } }
end end
def test_show_atom
get :show, :id => 2, :format => 'atom'
assert_response :success
assert_template 'changes'
# Inline image
assert @response.body.include?("&lt;img src=\"http://test.host/attachments/download/10\" alt=\"\" /&gt;")
end
def test_show_export_to_pdf def test_show_export_to_pdf
get :show, :id => 1, :format => 'pdf' get :show, :id => 3, :format => 'pdf'
assert_response :success assert_response :success
assert_equal 'application/pdf', @response.content_type assert_equal 'application/pdf', @response.content_type
assert @response.body.starts_with?('%PDF') assert @response.body.starts_with?('%PDF')
+9
View File
@@ -118,6 +118,15 @@ class NewsControllerTest < Test::Unit::TestCase
assert_equal User.find(2), comment.author assert_equal User.find(2), comment.author
end end
def test_empty_comment_should_not_be_added
@request.session[:user_id] = 2
assert_no_difference 'Comment.count' do
post :add_comment, :id => 1, :comment => { :comments => '' }
assert_response :success
assert_template 'show'
end
end
def test_destroy_comment def test_destroy_comment
comments_count = News.find(1).comments.size comments_count = News.find(1).comments.size
@request.session[:user_id] = 2 @request.session[:user_id] = 2
@@ -68,6 +68,16 @@ class ProjectsControllerTest < Test::Unit::TestCase
assert_equal Project.find_by_identifier('ecookbook'), assigns(:project) assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
end end
def test_show_should_not_fail_when_custom_values_are_nil
project = Project.find_by_identifier('ecookbook')
project.custom_values.first.update_attribute(:value, nil)
get :show, :id => 'ecookbook'
assert_response :success
assert_template 'show'
assert_not_nil assigns(:project)
assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
end
def test_private_subprojects_hidden def test_private_subprojects_hidden
get :show, :id => 'ecookbook' get :show, :id => 'ecookbook'
assert_response :success assert_response :success

Some files were not shown because too many files have changed in this diff Show More