# HG changeset patch
# User Chris Cannam
# Date 1310637053 -3600
# Node ID 7eba09d624db771a77805f82b0d407c8bc0177e1
# Parent b9aebdd7dd40e9199d4825a6ae008b826397fb2b# Parent 107d36338b70fa961bd32f62189a5aee56216f9b
Merge
diff -r b9aebdd7dd40 -r 7eba09d624db .gitignore
--- a/.gitignore Thu Jul 14 10:46:20 2011 +0100
+++ b/.gitignore Thu Jul 14 10:50:53 2011 +0100
@@ -1,4 +1,7 @@
+/.project
+/.loadpath
/config/additional_environment.rb
+/config/configuration.yml
/config/database.yml
/config/email.yml
/config/initializers/session_store.rb
@@ -7,6 +10,8 @@
/db/*.sqlite3
/db/schema.rb
/files/*
+/lib/redmine/scm/adapters/mercurial/redminehelper.pyc
+/lib/redmine/scm/adapters/mercurial/redminehelper.pyo
/log/*.log*
/log/mongrel_debug
/public/dispatch.*
diff -r b9aebdd7dd40 -r 7eba09d624db .hgignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Thu Jul 14 10:50:53 2011 +0100
@@ -0,0 +1,30 @@
+syntax: glob
+
+.project
+.loadpath
+config/additional_environment.rb
+config/configuration.yml
+config/database.yml
+config/email.yml
+config/initializers/session_store.rb
+coverage
+db/*.db
+db/*.sqlite3
+db/schema.rb
+files/*
+lib/redmine/scm/adapters/mercurial/redminehelper.pyc
+lib/redmine/scm/adapters/mercurial/redminehelper.pyo
+log/*.log*
+log/mongrel_debug
+public/dispatch.*
+public/plugin_assets
+tmp/cache/*
+tmp/sessions/*
+tmp/sockets/*
+tmp/test/*
+vendor/rails
+*.rbc
+.svn/
+.git/
+*~
+
diff -r b9aebdd7dd40 -r 7eba09d624db .svn/all-wcprops
--- a/.svn/all-wcprops Thu Jul 14 10:46:20 2011 +0100
+++ b/.svn/all-wcprops Thu Jul 14 10:50:53 2011 +0100
@@ -1,23 +1,5 @@
K 25
svn:wc:ra_dav:version-url
-V 24
-/svn/!svn/ver/4411/trunk
+V 38
+/svn/!svn/ver/6261/branches/1.2-stable
END
-Rakefile
-K 25
-svn:wc:ra_dav:version-url
-V 31
-/svn/!svn/ver/67/trunk/Rakefile
-END
-README.rdoc
-K 25
-svn:wc:ra_dav:version-url
-V 36
-/svn/!svn/ver/3849/trunk/README.rdoc
-END
-.gitignore
-K 25
-svn:wc:ra_dav:version-url
-V 35
-/svn/!svn/ver/3768/trunk/.gitignore
-END
diff -r b9aebdd7dd40 -r 7eba09d624db .svn/dir-prop-base
--- a/.svn/dir-prop-base Thu Jul 14 10:46:20 2011 +0100
+++ b/.svn/dir-prop-base Thu Jul 14 10:50:53 2011 +0100
@@ -4,7 +4,9 @@
e93f8b46-1217-0410-a6f0-8f06a7374b81:/trunk:1751
K 10
svn:ignore
-V 9
+V 28
coverage
+.project
+.loadpath
END
diff -r b9aebdd7dd40 -r 7eba09d624db .svn/entries
--- a/.svn/entries Thu Jul 14 10:46:20 2011 +0100
+++ b/.svn/entries Thu Jul 14 10:50:53 2011 +0100
@@ -1,14 +1,14 @@
10
dir
-4411
-http://redmine.rubyforge.org/svn/trunk
+6270
+http://redmine.rubyforge.org/svn/branches/1.2-stable
http://redmine.rubyforge.org/svn
-2010-11-17T18:27:38.712585Z
-4411
+2011-07-11T11:45:14.631570Z
+6261
jplang
has-props
@@ -32,6 +32,18 @@
app
dir
+.hgignore
+file
+
+
+
+
+
+cf080444603c5774a6f20da6bbafe234
+2011-03-28T04:54:13.617808Z
+5235
+tmaruyama
+
log
dir
@@ -41,7 +53,7 @@
-2010-09-23T14:37:44.367737Z
+2011-07-14T09:24:09.000000Z
bbf560d44f092d22a30d3a562436ad8c
2006-12-05T20:45:04.842118Z
67
@@ -75,7 +87,7 @@
-2010-09-23T14:37:44.367737Z
+2011-07-14T09:24:09.000000Z
67c937b1f1d0603e69f322de34bbfe04
2010-07-18T15:49:24.341728Z
3849
@@ -121,45 +133,45 @@
script
dir
-doc
-dir
+.gitignore
+file
+
+
+
+
+2011-07-14T09:24:09.000000Z
+84dbba0b6ddcd80d28c62a3f8e344bc4
+2011-02-15T11:04:52.942730Z
+4834
+tmaruyama
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+477
config
dir
-.gitignore
-file
-
-
-
-
-2010-09-23T14:37:44.363818Z
-201a803b90bbd2a1624c4ce1dd260098
-2010-06-09T22:01:21.132822Z
-3768
-edavis10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-322
+doc
+dir
lib
dir
diff -r b9aebdd7dd40 -r 7eba09d624db .svn/text-base/.gitignore.svn-base
--- a/.svn/text-base/.gitignore.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/.svn/text-base/.gitignore.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,4 +1,7 @@
+/.project
+/.loadpath
/config/additional_environment.rb
+/config/configuration.yml
/config/database.yml
/config/email.yml
/config/initializers/session_store.rb
@@ -7,6 +10,8 @@
/db/*.sqlite3
/db/schema.rb
/files/*
+/lib/redmine/scm/adapters/mercurial/redminehelper.pyc
+/lib/redmine/scm/adapters/mercurial/redminehelper.pyo
/log/*.log*
/log/mongrel_debug
/public/dispatch.*
diff -r b9aebdd7dd40 -r 7eba09d624db .svn/text-base/.hgignore.svn-base
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/text-base/.hgignore.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -0,0 +1,29 @@
+syntax: glob
+
+.project
+.loadpath
+config/additional_environment.rb
+config/configuration.yml
+config/database.yml
+config/email.yml
+config/initializers/session_store.rb
+coverage
+db/*.db
+db/*.sqlite3
+db/schema.rb
+files/*
+lib/redmine/scm/adapters/mercurial/redminehelper.pyc
+lib/redmine/scm/adapters/mercurial/redminehelper.pyo
+log/*.log*
+log/mongrel_debug
+public/dispatch.*
+public/plugin_assets
+tmp/*
+tmp/cache/*
+tmp/sessions/*
+tmp/sockets/*
+tmp/test/*
+vendor/rails
+*.rbc
+.svn/
+.git/
diff -r b9aebdd7dd40 -r 7eba09d624db app/.svn/all-wcprops
--- a/app/.svn/all-wcprops Thu Jul 14 10:46:20 2011 +0100
+++ b/app/.svn/all-wcprops Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
K 25
svn:wc:ra_dav:version-url
-V 28
-/svn/!svn/ver/4411/trunk/app
+V 42
+/svn/!svn/ver/6254/branches/1.2-stable/app
END
diff -r b9aebdd7dd40 -r 7eba09d624db app/.svn/entries
--- a/app/.svn/entries Thu Jul 14 10:46:20 2011 +0100
+++ b/app/.svn/entries Thu Jul 14 10:50:53 2011 +0100
@@ -1,15 +1,15 @@
10
dir
-4411
-http://redmine.rubyforge.org/svn/trunk/app
+6270
+http://redmine.rubyforge.org/svn/branches/1.2-stable/app
http://redmine.rubyforge.org/svn
-2010-11-17T18:27:38.712585Z
-4411
-jplang
+2011-07-11T02:08:23.222641Z
+6254
+tmaruyama
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/all-wcprops
--- a/app/controllers/.svn/all-wcprops Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/all-wcprops Thu Jul 14 10:50:53 2011 +0100
@@ -1,299 +1,77 @@
K 25
svn:wc:ra_dav:version-url
-V 40
-/svn/!svn/ver/4411/trunk/app/controllers
+V 54
+/svn/!svn/ver/6209/branches/1.2-stable/app/controllers
+END
+boards_controller.rb
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/boards_controller.rb
END
issues_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/4411/trunk/app/controllers/issues_controller.rb
+V 75
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/issues_controller.rb
END
-queries_controller.rb
+news_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/3684/trunk/app/controllers/queries_controller.rb
-END
-sys_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/3201/trunk/app/controllers/sys_controller.rb
-END
-mail_handler_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 67
-/svn/!svn/ver/3202/trunk/app/controllers/mail_handler_controller.rb
-END
-watchers_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/3798/trunk/app/controllers/watchers_controller.rb
-END
-auto_completes_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 69
-/svn/!svn/ver/3945/trunk/app/controllers/auto_completes_controller.rb
-END
-my_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 57
-/svn/!svn/ver/4224/trunk/app/controllers/my_controller.rb
-END
-comments_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/4172/trunk/app/controllers/comments_controller.rb
-END
-members_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/3784/trunk/app/controllers/members_controller.rb
-END
-welcome_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/2941/trunk/app/controllers/welcome_controller.rb
-END
-context_menus_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 68
-/svn/!svn/ver/4242/trunk/app/controllers/context_menus_controller.rb
+V 73
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/news_controller.rb
END
journals_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/4034/trunk/app/controllers/journals_controller.rb
-END
-workflows_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 64
-/svn/!svn/ver/3536/trunk/app/controllers/workflows_controller.rb
-END
-time_entry_reports_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 73
-/svn/!svn/ver/4232/trunk/app/controllers/time_entry_reports_controller.rb
-END
-reports_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/3692/trunk/app/controllers/reports_controller.rb
-END
-project_enumerations_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 75
-/svn/!svn/ver/4075/trunk/app/controllers/project_enumerations_controller.rb
-END
-settings_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/4220/trunk/app/controllers/settings_controller.rb
+V 77
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/journals_controller.rb
END
timelog_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/4410/trunk/app/controllers/timelog_controller.rb
-END
-custom_fields_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 68
-/svn/!svn/ver/3627/trunk/app/controllers/custom_fields_controller.rb
+V 76
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/timelog_controller.rb
END
users_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/4382/trunk/app/controllers/users_controller.rb
-END
-issue_moves_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 66
-/svn/!svn/ver/4292/trunk/app/controllers/issue_moves_controller.rb
-END
-files_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/4177/trunk/app/controllers/files_controller.rb
+V 74
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/users_controller.rb
END
application_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 66
-/svn/!svn/ver/4286/trunk/app/controllers/application_controller.rb
+V 80
+/svn/!svn/ver/6209/branches/1.2-stable/app/controllers/application_controller.rb
END
-ldap_auth_sources_controller.rb
+activities_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 72
-/svn/!svn/ver/3744/trunk/app/controllers/ldap_auth_sources_controller.rb
-END
-auth_sources_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 67
-/svn/!svn/ver/3744/trunk/app/controllers/auth_sources_controller.rb
-END
-previews_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/4174/trunk/app/controllers/previews_controller.rb
+V 79
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/activities_controller.rb
END
search_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/3806/trunk/app/controllers/search_controller.rb
+V 75
+/svn/!svn/ver/6202/branches/1.2-stable/app/controllers/search_controller.rb
END
-messages_controller.rb
+repositories_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/3528/trunk/app/controllers/messages_controller.rb
+V 81
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/repositories_controller.rb
END
issue_relations_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 70
-/svn/!svn/ver/3591/trunk/app/controllers/issue_relations_controller.rb
-END
-versions_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/4354/trunk/app/controllers/versions_controller.rb
-END
-boards_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/3942/trunk/app/controllers/boards_controller.rb
-END
-attachments_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 66
-/svn/!svn/ver/3281/trunk/app/controllers/attachments_controller.rb
-END
-news_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 59
-/svn/!svn/ver/4174/trunk/app/controllers/news_controller.rb
-END
-trackers_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/3627/trunk/app/controllers/trackers_controller.rb
-END
-groups_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/3934/trunk/app/controllers/groups_controller.rb
-END
-issue_statuses_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 69
-/svn/!svn/ver/3416/trunk/app/controllers/issue_statuses_controller.rb
-END
-roles_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/3627/trunk/app/controllers/roles_controller.rb
-END
-wikis_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/3370/trunk/app/controllers/wikis_controller.rb
-END
-repositories_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 67
-/svn/!svn/ver/3680/trunk/app/controllers/repositories_controller.rb
-END
-admin_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/3200/trunk/app/controllers/admin_controller.rb
+V 84
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/issue_relations_controller.rb
END
projects_controller.rb
K 25
svn:wc:ra_dav:version-url
-V 63
-/svn/!svn/ver/4397/trunk/app/controllers/projects_controller.rb
+V 77
+/svn/!svn/ver/6198/branches/1.2-stable/app/controllers/projects_controller.rb
END
-account_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/3906/trunk/app/controllers/account_controller.rb
-END
-calendars_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 64
-/svn/!svn/ver/4388/trunk/app/controllers/calendars_controller.rb
-END
-issue_categories_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 71
-/svn/!svn/ver/3597/trunk/app/controllers/issue_categories_controller.rb
-END
-gantts_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/4388/trunk/app/controllers/gantts_controller.rb
-END
-documents_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 64
-/svn/!svn/ver/3597/trunk/app/controllers/documents_controller.rb
-END
-wiki_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 59
-/svn/!svn/ver/4303/trunk/app/controllers/wiki_controller.rb
-END
-activities_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 65
-/svn/!svn/ver/4047/trunk/app/controllers/activities_controller.rb
-END
-enumerations_controller.rb
-K 25
-svn:wc:ra_dav:version-url
-V 67
-/svn/!svn/ver/3524/trunk/app/controllers/enumerations_controller.rb
-END
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/entries
--- a/app/controllers/.svn/entries Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/entries Thu Jul 14 10:50:53 2011 +0100
@@ -1,14 +1,14 @@
10
dir
-4411
-http://redmine.rubyforge.org/svn/trunk/app/controllers
+6270
+http://redmine.rubyforge.org/svn/branches/1.2-stable/app/controllers
http://redmine.rubyforge.org/svn
-2010-11-17T18:27:38.712585Z
-4411
+2011-07-09T18:49:13.583984Z
+6209
jplang
@@ -32,10 +32,10 @@
-2010-11-19T13:04:46.996826Z
-e6c77385e49176b593367b44e7b33f3e
-2010-11-17T18:27:38.712585Z
-4411
+2011-07-14T09:28:10.000000Z
+c8deaf810284940ffaf93b34770e68c1
+2011-07-09T09:11:13.773613Z
+6198
jplang
has-props
@@ -58,7 +58,7 @@
-12834
+12830
queries_controller.rb
file
@@ -66,11 +66,11 @@
-2010-09-23T14:37:44.399747Z
-7ad6758cfd160c4b6ef6d71be06e087c
-2010-04-19T15:08:28.751734Z
-3684
-edavis10
+2011-07-14T09:24:21.000000Z
+d5fb2cc0fcbed592991370967f38af2b
+2011-04-03T14:31:32.940784Z
+5304
+jplang
has-props
@@ -92,7 +92,7 @@
-2999
+3261
sys_controller.rb
file
@@ -100,7 +100,7 @@
-2010-09-23T14:37:44.399747Z
+2011-07-14T09:24:09.000000Z
7a73aba15fcd447531d1552de01706d9
2009-12-20T09:44:28.044710Z
3201
@@ -134,11 +134,11 @@
-2010-09-23T14:37:44.395735Z
-612f3e7497e14c728934e83fbe5778c4
-2009-12-20T09:45:04.782778Z
-3202
-jplang
+2011-07-14T09:24:21.000000Z
+a198d0cd4a30c00a40a646cecbbe71e2
+2011-05-18T07:13:08.785903Z
+5838
+tmaruyama
has-props
@@ -160,7 +160,7 @@
-1588
+1571
watchers_controller.rb
file
@@ -168,11 +168,11 @@
-2010-09-23T14:37:44.399747Z
-3ee494bd8196306eab8913bd462b44da
-2010-06-20T16:08:15.578906Z
-3798
-edavis10
+2011-07-14T09:24:21.000000Z
+74083636df6bb82e8dc1f4fbd3da2882
+2011-04-05T12:09:15.508559Z
+5320
+jplang
has-props
@@ -194,7 +194,7 @@
-3234
+3021
auto_completes_controller.rb
file
@@ -202,33 +202,33 @@
-2010-09-23T14:37:44.391741Z
-8cd8e21323a4500a05c26e4ebdde1812
-2010-08-17T15:03:58.074505Z
-3945
-edavis10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-665
+2011-07-14T09:24:09.000000Z
+edbdb443ff7cc8f299f7772b3532eca1
+2010-12-12T16:06:43.892596Z
+4503
+jplang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+772
my_controller.rb
file
@@ -236,11 +236,11 @@
-2010-11-19T13:04:46.996826Z
-b465d7aeca2d6b4cc11159ae9bc7349e
-2010-09-28T22:13:11.637219Z
-4224
-edavis10
+2011-07-14T09:24:09.000000Z
+40ea055e0f9f9aa83680751fdab5a0a5
+2010-12-12T14:25:23.262992Z
+4497
+jplang
has-props
@@ -262,7 +262,7 @@
-6021
+5768
comments_controller.rb
file
@@ -270,7 +270,7 @@
-2010-09-24T12:48:26.271687Z
+2011-07-14T09:24:09.000000Z
c2289eb9b654117a101c072955d4c705
2010-09-23T15:20:19.085385Z
4172
@@ -304,7 +304,7 @@
-2010-09-23T14:37:44.395735Z
+2011-07-14T09:24:09.000000Z
20e245fa61dc0dcb2f105a8f0e6af98c
2010-06-19T19:51:43.174421Z
3784
@@ -332,13 +332,47 @@
3447
+context_menus_controller.rb
+file
+
+
+
+
+2011-07-14T09:24:21.000000Z
+ee556c18cb658bef786cc6f69388f9b8
+2011-04-17T15:17:18.418900Z
+5495
+jplang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2432
+
welcome_controller.rb
file
-2010-09-23T14:37:44.403745Z
+2011-07-14T09:24:09.000000Z
95ad1acf7766861a4dbd0aebd9c847de
2009-10-21T03:21:31.657956Z
2941
@@ -366,51 +400,17 @@
1091
-context_menus_controller.rb
-file
-
-
-
-
-2010-11-19T13:04:46.996826Z
-2db29b69c3f0130e470a0a11dfc1f28b
-2010-10-08T03:09:51.863032Z
-4242
-jbbarth
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1821
-
journals_controller.rb
file
-2010-09-23T14:37:44.395735Z
-deb481ad0f862b9305b79f292d59fb51
-2010-08-23T15:04:36.844654Z
-4034
-edavis10
+2011-07-14T09:28:10.000000Z
+70d5ea1cc9e7df479a2f24f04b530502
+2011-07-09T09:11:13.773613Z
+6198
+jplang
has-props
@@ -432,41 +432,7 @@
-3439
-
-workflows_controller.rb
-file
-
-
-
-
-2010-09-23T14:37:44.403745Z
-5052c701a12ad27e88950dd4a745b0f8
-2010-03-04T05:33:45.236699Z
-3536
-edavis10
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3346
+4105
time_entry_reports_controller.rb
file
@@ -474,7 +440,7 @@
-2010-11-19T13:04:46.996826Z
+2011-07-14T09:24:09.000000Z
dadcb57d89dc3c90c5fa099b143c07f8
2010-10-05T16:07:17.015270Z
4232
@@ -502,13 +468,47 @@
9308
+workflows_controller.rb
+file
+
+
+
+
+2011-07-14T09:24:09.000000Z
+73cdba17212ad890eea7b7c7ee140d7e
+2011-02-20T15:38:07.840581Z
+4895
+jplang
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4041
+
reports_controller.rb
file
-2010-09-23T14:37:44.399747Z
+2011-07-14T09:24:09.000000Z
8f7e6e7308912a6169a700b0c88174a0
2010-04-27T16:43:52.584075Z
3692
@@ -542,7 +542,7 @@
-2010-09-24T12:48:26.271687Z
+2011-07-14T09:24:09.000000Z
828b364ba2850ceddb3caa566bf10124
2010-09-10T16:00:49.687515Z
4075
@@ -576,10 +576,10 @@
-2010-11-19T13:04:46.996826Z
-7984019db8d0beb1d7ff158390d4ad68
-2010-11-16T20:27:45.364396Z
-4410
+2011-07-14T09:28:10.000000Z
+341ec8f56b1a1a24fd23ff8b4e1fe7b3
+2011-07-09T09:11:13.773613Z
+6198
jplang
has-props
@@ -602,7 +602,41 @@
-8623
+12440
+
+settings_controller.rb
+file
+
+
+
+
+2011-07-14T09:24:21.000000Z
+cef6dc401dea01bdddca8a8a405aeaee
+2011-05-18T02:18:47.811055Z
+5827
+tmaruyama
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2286
custom_fields_controller.rb
file
@@ -610,11 +644,11 @@
-2010-09-23T14:37:44.391741Z
-00272455ac5be11da48f92c4a443c538
-2010-04-03T11:54:24.331654Z
-3627
-winterheart
+2011-07-14T09:24:21.000000Z
+e87f5ffac690480de57ac0a90daad01c
+2011-05-01T23:15:03.415033Z
+5611
+tmaruyama
has-props
@@ -636,19 +670,19 @@
-2373
+2395
-settings_controller.rb
+users_controller.rb
file
-2010-11-19T13:04:46.996826Z
-4328cabdf111342d147b245bc61bb75e
-2010-09-28T20:19:55.214366Z
-4220
-edavis10
+2011-07-14T09:28:10.000000Z
+858ad5381dc0944da7954e1a8dae60ac
+2011-07-09T09:11:13.773613Z
+6198
+jplang
has-props
@@ -670,7 +704,7 @@
-2239
+8639
issue_moves_controller.rb
file
@@ -678,67 +712,33 @@
-2010-11-19T13:04:47.000764Z
-cacd6ffe0ce299e2ede9d45b7ef8af42
-2010-10-25T18:44:46.868009Z
-4292
-edavis10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2441
-
-users_controller.rb
-file
-
-
-
-
-2010-11-19T13:04:47.000764Z
-3af0a81ba74621dc21d877a579b39d9c
-2010-11-07T14:15:01.891476Z
-4382
-jplang
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-7565
+2011-07-14T09:24:21.000000Z
+cbd01754dc3edc7ce30bd9e401608908
+2011-05-17T03:59:02.899695Z
+5821
+tmaruyama
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2435
files_controller.rb
file
@@ -746,33 +746,33 @@
-2010-11-19T13:04:47.000764Z
-f0246e8f8dde5ea7b93e4dc2162181fc
-2010-09-26T08:07:41.604064Z
-4177
-jplang
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1289
+2011-07-14T09:24:21.000000Z
+e40d3a7211765dd6a7dd0fde90906bab
+2011-05-18T07:12:48.748391Z
+5837
+tmaruyama
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1273
application_controller.rb
file
@@ -780,10 +780,10 @@
-2010-11-19T13:04:47.000764Z
-8f7d4c9d306ae9d59ea0e064466454d1
-2010-10-23T11:07:04.019894Z
-4286
+2011-07-14T09:28:10.000000Z
+558cc843d43a24e2cd334571c32a7656
+2011-07-09T18:49:13.583984Z
+6209
jplang
has-props
@@ -806,41 +806,7 @@
-13669
-
-previews_controller.rb
-file
-
-
-
-
-2010-11-19T13:04:47.000764Z
-c5ae4fae18159e70fd81c2487bb1daa1
-2010-09-24T16:26:46.819682Z
-4174
-edavis10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-957
+16538
auth_sources_controller.rb
file
@@ -848,7 +814,7 @@
-2010-09-23T14:37:44.391741Z
+2011-07-14T09:24:09.000000Z
237280766d09418161536250d514a7bf
2010-05-23T03:16:31.304135Z
3744
@@ -882,7 +848,7 @@
-2010-09-23T14:37:44.395735Z
+2011-07-14T09:24:09.000000Z
5f7b9cb2e9c8a60db58ea0833cf481c5
2010-05-23T03:16:31.304135Z
3744
@@ -910,17 +876,51 @@
917
+previews_controller.rb
+file
+
+
+
+
+2011-07-14T09:24:21.000000Z
+fa4b7467e77f8a7bc86ff60a68052684
+2011-03-28T21:45:30.892324Z
+5246
+jplang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1754
+
search_controller.rb
file
-2010-09-23T14:37:44.399747Z
-0015154998f830227b636ee423f007f3
-2010-06-20T20:01:32.722003Z
-3806
-edavis10
+2011-07-14T09:28:10.000000Z
+47432306ab84ca571b40b037b3c34095
+2011-07-09T11:26:35.866966Z
+6202
+jplang
has-props
@@ -942,7 +942,7 @@
-3961
+4001
messages_controller.rb
file
@@ -950,7 +950,7 @@
-2010-09-23T14:37:44.395735Z
+2011-07-14T09:24:09.000000Z
f3f4378ec15e1401ead0dcac4e9cb059
2010-03-03T17:05:00.967826Z
3528
@@ -984,7 +984,7 @@
-2010-11-19T13:04:47.000764Z
+2011-07-14T09:24:09.000000Z
a98fb262a20669600a85c0f72202c5e6
2010-11-01T13:13:32.982466Z
4354
@@ -1018,11 +1018,11 @@
-2010-09-23T14:37:44.395735Z
-c57448661f2eaab81c76f23d7f51e0ab
-2010-03-16T15:17:47.586688Z
-3591
-edavis10
+2011-07-14T09:28:10.000000Z
+00adf3dbe7851ad6127cf120df999f7b
+2011-07-09T09:11:13.773613Z
+6198
+jplang
has-props
@@ -1044,7 +1044,7 @@
-2220
+2450
boards_controller.rb
file
@@ -1052,11 +1052,11 @@
-2010-09-23T14:37:44.391741Z
-52638c82da929081099076d5aa0f9212
-2010-08-16T23:39:27.396462Z
-3942
-edavis10
+2011-07-14T09:28:10.000000Z
+4800c888c351ca91dd2e9fdf1bbab57b
+2011-07-09T09:11:13.773613Z
+6198
+jplang
has-props
@@ -1086,11 +1086,11 @@
-2010-09-23T14:37:44.391741Z
-21c0e5d894d1429ac39f3253ae021594
-2010-01-05T18:16:03.565347Z
-3281
-jplang
+2011-07-14T09:24:21.000000Z
+c679c8cbf25d1c5d30e2f88bb177a202
+2011-05-18T07:12:27.059090Z
+5836
+tmaruyama
has-props
@@ -1112,7 +1112,7 @@
-2982
+2954
news_controller.rb
file
@@ -1120,11 +1120,11 @@
-2010-11-19T13:04:47.000764Z
-d9e36fcf69f18973b274648b7b70dccf
-2010-09-24T16:26:46.819682Z
-4174
-edavis10
+2011-07-14T09:28:10.000000Z
+3b6f0957dcc31aa8c48bef64ed452d0b
+2011-07-09T09:11:13.773613Z
+6198
+jplang
has-props
@@ -1146,7 +1146,7 @@
-3221
+3421
trackers_controller.rb
file
@@ -1154,7 +1154,7 @@
-2010-09-23T14:37:44.399747Z
+2011-07-14T09:24:09.000000Z
a5e793eb94e501be4c1a39acc65cc568
2010-04-03T11:54:24.331654Z
3627
@@ -1188,11 +1188,11 @@
-2010-09-23T14:37:44.395735Z
-77209ec52ddcefafb0bfbb76195167ec
-2010-08-10T22:37:00.826946Z
-3934
-jbbarth
+2011-07-14T09:24:21.000000Z
+4e6c1f74ad57c0df68dfb3a6c6432a2e
+2011-04-01T16:47:30.350690Z
+5284
+jplang
has-props
@@ -1214,7 +1214,7 @@
-5214
+5213
issue_statuses_controller.rb
file
@@ -1222,7 +1222,7 @@
-2010-09-23T14:37:44.395735Z
+2011-07-14T09:24:09.000000Z
f0fdda9126d71c0b2d4638de50ab1097
2010-02-12T19:15:39.389877Z
3416
@@ -1256,11 +1256,11 @@
-2010-09-23T14:37:44.399747Z
-28f2e44219870c62c9844354b78af6e1
-2010-04-03T11:54:24.331654Z
-3627
-winterheart
+2011-07-14T09:24:21.000000Z
+18be86518ea841401ee1c2b3233d72a4
+2011-05-01T23:15:03.415033Z
+5611
+tmaruyama
has-props
@@ -1282,7 +1282,7 @@
-2612
+2638
wikis_controller.rb
file
@@ -1290,7 +1290,7 @@
-2010-09-23T14:37:44.403745Z
+2011-07-14T09:24:09.000000Z
7ae79a9d22586240a01af73834b718a3
2010-02-05T16:57:02.094258Z
3370
@@ -1324,10 +1324,10 @@
-2010-09-23T14:37:44.399747Z
-a90fd2992bc17c6cee999369521194c4
-2010-04-17T12:51:46.860438Z
-3680
+2011-07-14T09:28:10.000000Z
+03fa916999a68f9d1014925de3ad1981
+2011-07-09T09:11:13.773613Z
+6198
jplang
has-props
@@ -1350,7 +1350,7 @@
-10750
+12687
admin_controller.rb
file
@@ -1358,11 +1358,11 @@
-2010-09-23T14:37:44.391741Z
-ed65a11326fe54914ba3a750a2b6f943
-2009-12-19T20:33:24.113306Z
-3200
-jplang
+2011-07-14T09:24:21.000000Z
+4577094f50fcbc76c8dba52341a2fbe2
+2011-04-25T23:21:34.669083Z
+5550
+tmaruyama
has-props
@@ -1384,7 +1384,7 @@
-3104
+3119
projects_controller.rb
file
@@ -1392,10 +1392,10 @@
-2010-11-19T13:04:47.000764Z
-b0f584d53a742f6c89b157030f9d6a8d
-2010-11-13T10:05:43.644565Z
-4397
+2011-07-14T09:28:10.000000Z
+dccb25f35e9cb7bf110cc372d9d06fb0
+2011-07-09T09:11:13.773613Z
+6198
jplang
has-props
@@ -1418,7 +1418,7 @@
-10011
+10029
account_controller.rb
file
@@ -1426,11 +1426,11 @@
-2010-09-23T14:37:44.391741Z
-d0ff6be1c749b765d9d64bef64c27537
-2010-08-03T15:26:50.842290Z
-3906
-edavis10
+2011-07-14T09:24:09.000000Z
+7b162cad903bb22948f7040a48509256
+2011-01-23T11:40:07.678287Z
+4757
+jplang
has-props
@@ -1452,7 +1452,7 @@
-8962
+9350
calendars_controller.rb
file
@@ -1460,10 +1460,10 @@
-2010-11-19T13:04:47.000764Z
-0be20cab6d5ea49f428a90cf3afef3e3
-2010-11-07T22:38:10.728638Z
-4388
+2011-07-14T09:24:21.000000Z
+4bc844343a8613ab25bd4c76969d566a
+2011-04-01T14:34:44.070899Z
+5276
jplang
@@ -1486,7 +1486,7 @@
-1390
+2155
issue_categories_controller.rb
file
@@ -1494,11 +1494,11 @@
-2010-09-23T14:37:44.395735Z
-119ceb4a27aa554d03867f46cb142d0e
-2010-03-17T15:41:58.766740Z
-3597
-edavis10
+2011-07-14T09:24:21.000000Z
+c42630be286026f052791d256b487246
+2011-05-01T23:15:03.415033Z
+5611
+tmaruyama
has-props
@@ -1520,7 +1520,7 @@
-3338
+3364
gantts_controller.rb
file
@@ -1528,10 +1528,10 @@
-2010-11-19T13:04:47.000764Z
-81dbee1745da99b9ea499f3fbe1d3944
-2010-11-07T22:38:10.728638Z
-4388
+2011-07-14T09:24:21.000000Z
+8093015b8337589c3a8dd96f912a626c
+2011-04-01T14:34:44.070899Z
+5276
jplang
@@ -1554,7 +1554,7 @@
-1019
+1786
documents_controller.rb
file
@@ -1562,7 +1562,7 @@
-2010-09-23T14:37:44.391741Z
+2011-07-14T09:24:09.000000Z
c2c68bf5fa3ed22a8f55c8414d1efce9
2010-03-17T15:41:58.766740Z
3597
@@ -1596,11 +1596,11 @@
-2010-11-19T13:04:47.004764Z
-0af823002ab9c7e8f59b3d12cf6267e9
-2010-10-28T21:25:38.778234Z
-4303
-edavis10
+2011-07-14T09:24:21.000000Z
+4e9a4e1dd2d09a4cee7f4df56e8659f1
+2011-05-17T04:34:44.952857Z
+5824
+tmaruyama
has-props
@@ -1622,7 +1622,7 @@
-10145
+10000
activities_controller.rb
file
@@ -1630,33 +1630,33 @@
-2010-09-24T12:48:26.275788Z
-88f55d118861ffaca0992fa5ec55d51f
-2010-08-27T14:05:54.014502Z
-4047
-edavis10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1952
+2011-07-14T09:28:10.000000Z
+4d0e519d63fce8db9095adc7f1eb554b
+2011-07-09T09:11:13.773613Z
+6198
+jplang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2813
enumerations_controller.rb
file
@@ -1664,11 +1664,11 @@
-2010-09-23T14:37:44.391741Z
-1caaedc7bb0a3085878dc94446c70ab0
-2010-03-02T20:03:09.514061Z
-3524
-jplang
+2011-07-14T09:24:21.000000Z
+4c46e4cd141ad0a3534b60df7be534bc
+2011-05-01T23:15:03.415033Z
+5611
+tmaruyama
has-props
@@ -1690,5 +1690,5 @@
-2706
+2734
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/account_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/account_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/account_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -203,12 +203,24 @@
self.logged_user = user
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
- token = Token.create(:user => user, :action => 'autologin')
- cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
+ set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user })
redirect_back_or_default :controller => 'my', :action => 'page'
end
+
+ def set_autologin_cookie(user)
+ token = Token.create(:user => user, :action => 'autologin')
+ cookie_name = Redmine::Configuration['autologin_cookie_name'] || 'autologin'
+ cookie_options = {
+ :value => token.value,
+ :expires => 1.year.from_now,
+ :path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
+ :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
+ :httponly => true
+ }
+ cookies[cookie_name] = cookie_options
+ end
# Onthefly creation failed, display the registration form to fill/fix attributes
def onthefly_creation_failed(user, auth_source_options = { })
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/activities_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/activities_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/activities_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,11 +1,28 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class ActivitiesController < ApplicationController
menu_item :activity
before_filter :find_optional_project
- accept_key_auth :index
+ accept_rss_auth :index
def index
@days = Setting.activity_days_default.to_i
-
+
if params[:from]
begin; @date_to = params[:from].to_date + 1; rescue; end
end
@@ -14,18 +31,18 @@
@date_from = @date_to - @days
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
@author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id]))
-
- @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
+
+ @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
:with_subprojects => @with_subprojects,
:author => @author)
@activity.scope_select {|t| !params["show_#{t}"].nil?}
@activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty?
events = @activity.events(@date_from, @date_to)
-
- if events.empty? || stale?(:etag => [events.first, User.current])
+
+ if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
respond_to do |format|
- format.html {
+ format.html {
@events_by_day = events.group_by(&:event_date)
render :layout => false if request.xhr?
}
@@ -40,7 +57,7 @@
}
end
end
-
+
rescue ActiveRecord::RecordNotFound
render_404
end
@@ -55,5 +72,4 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/admin_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/admin_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/admin_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -17,9 +17,7 @@
class AdminController < ApplicationController
layout 'admin'
-
before_filter :require_admin
-
helper :sort
include SortHelper
@@ -30,22 +28,20 @@
def projects
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
-
unless params[:name].blank?
name = "%#{params[:name].strip.downcase}%"
c << ["LOWER(identifier) LIKE ? OR LOWER(name) LIKE ?", name, name]
end
-
@projects = Project.find :all, :order => 'lft',
:conditions => c.conditions
render :action => "projects", :layout => false if request.xhr?
end
-
+
def plugins
@plugins = Redmine::Plugin.all
end
-
+
# Loads the default configuration
# (roles, trackers, statuses, workflow, enumerations)
def default_configuration
@@ -59,7 +55,7 @@
end
redirect_to :action => 'index'
end
-
+
def test_email
raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
# Force ActionMailer to raise delivery errors so we can catch it
@@ -73,14 +69,16 @@
ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
redirect_to :controller => 'settings', :action => 'edit', :tab => 'notifications'
end
-
+
def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name
@checklist = [
- [:text_default_administrator_account_changed, User.find(:first, :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?],
+ [:text_default_administrator_account_changed,
+ User.find(:first,
+ :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?],
[:text_file_repository_writable, File.writable?(Attachment.storage_path)],
- [:text_plugin_assets_writable, File.writable?(Engines.public_directory)],
- [:text_rmagick_available, Object.const_defined?(:Magick)]
+ [:text_plugin_assets_writable, File.writable?(Engines.public_directory)],
+ [:text_rmagick_available, Object.const_defined?(:Magick)]
]
- end
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/application_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/application_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/application_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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.
@@ -18,34 +18,37 @@
require 'uri'
require 'cgi'
+class Unauthorized < Exception; end
+
class ApplicationController < ActionController::Base
include Redmine::I18n
layout 'base'
- exempt_from_layout 'builder'
-
+ exempt_from_layout 'builder', 'rsb'
+
# Remove broken cookie after upgrade from 0.8.x (#4292)
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360
# TODO: remove it when Rails is fixed
before_filter :delete_broken_cookies
def delete_broken_cookies
if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/
- cookies.delete '_redmine_session'
+ cookies.delete '_redmine_session'
redirect_to home_path
return false
end
end
-
+
before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password
protect_from_forgery
-
+
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
-
+ rescue_from ::Unauthorized, :with => :deny_access
+
include Redmine::Search::Controller
include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper
-
+
Redmine::Scm::Base.all.each do |scm|
require_dependency "repository/#{scm.underscore}"
end
@@ -56,7 +59,7 @@
# Find the current user
User.current = find_current_user
end
-
+
# Returns the current user or nil if no user is logged in
# and starts a session if needed
def find_current_user
@@ -68,13 +71,13 @@
user = User.try_to_autologin(cookies[:autologin])
session[:user_id] = user.id if user
user
- elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action])
+ elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session
User.find_by_rss_key(params[:key])
- elsif Setting.rest_api_enabled? && ['xml', 'json'].include?(params[:format])
- if params[:key].present? && accept_key_auth_actions.include?(params[:action])
+ elsif Setting.rest_api_enabled? && accept_api_auth?
+ if (key = api_key_from_request)
# Use API key
- User.find_by_api_key(params[:key])
+ User.find_by_api_key(key)
else
# HTTP Basic, either username/password or API key/random
authenticate_with_http_basic do |username, password|
@@ -94,14 +97,14 @@
User.current = User.anonymous
end
end
-
+
# check if login is globally required to access the application
def check_if_login_required
# no check needed if user is already logged in
return true if User.current.logged?
require_login if Setting.login_required?
- end
-
+ end
+
def set_localization
lang = nil
if User.current.logged?
@@ -117,7 +120,7 @@
lang ||= Setting.default_language
set_language_if_valid(lang)
end
-
+
def require_login
if !User.current.logged?
# Extract only the basic url parameters on non-GET requests
@@ -146,7 +149,7 @@
end
true
end
-
+
def deny_access
User.current.logged? ? render_403 : require_login
end
@@ -197,7 +200,7 @@
# Finds and sets @project based on @object.project
def find_project_from_association
render_404 unless @object.present?
-
+
@project = @object.project
rescue ActiveRecord::RecordNotFound
render_404
@@ -221,12 +224,16 @@
def find_issues
@issues = Issue.find_all_by_id(params[:id] || params[:ids])
raise ActiveRecord::RecordNotFound if @issues.empty?
+ if @issues.detect {|issue| !issue.visible?}
+ deny_access
+ return
+ end
@projects = @issues.collect(&:project).compact.uniq
@project = @projects.first if @projects.size == 1
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
# Check if project is unique before bulk operations
def check_project_uniqueness
unless @project
@@ -235,7 +242,7 @@
return false
end
end
-
+
# make sure that the user is a member of the project (or admin) if project is private
# used as a before_filter for actions that do not require any particular permission on the project
def check_project_privacy
@@ -271,27 +278,28 @@
end
end
redirect_to default
+ false
end
-
+
def render_403(options={})
@project = nil
render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
return false
end
-
+
def render_404(options={})
render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
return false
end
-
+
# Renders an error response
def render_error(arg)
arg = {:message => arg} unless arg.is_a?(Hash)
-
+
@message = arg[:message]
@message = l(@message) if @message.is_a?(Symbol)
@status = arg[:status] || 500
-
+
respond_to do |format|
format.html {
render :template => 'common/error', :layout => use_layout, :status => @status
@@ -309,15 +317,15 @@
def use_layout
request.xhr? ? false : 'base'
end
-
+
def invalid_authenticity_token
if api_request?
logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)."
end
render_error "Invalid form authenticity token."
end
-
- def render_feed(items, options={})
+
+ def render_feed(items, options={})
@items = items || []
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
@items = @items.slice(0, Setting.feeds_limit.to_i)
@@ -325,15 +333,42 @@
render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
end
+ # TODO: remove in Redmine 1.4
def self.accept_key_auth(*actions)
- actions = actions.flatten.map(&:to_s)
- write_inheritable_attribute('accept_key_auth_actions', actions)
+ ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
+ accept_rss_auth(*actions)
+ end
+
+ # TODO: remove in Redmine 1.4
+ def accept_key_auth_actions
+ ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth_actions is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
+ self.class.accept_rss_auth
end
- def accept_key_auth_actions
- self.class.read_inheritable_attribute('accept_key_auth_actions') || []
+ def self.accept_rss_auth(*actions)
+ if actions.any?
+ write_inheritable_attribute('accept_rss_auth_actions', actions)
+ else
+ read_inheritable_attribute('accept_rss_auth_actions') || []
+ end
end
+ def accept_rss_auth?(action=action_name)
+ self.class.accept_rss_auth.include?(action.to_sym)
+ end
+
+ def self.accept_api_auth(*actions)
+ if actions.any?
+ write_inheritable_attribute('accept_api_auth_actions', actions)
+ else
+ read_inheritable_attribute('accept_api_auth_actions') || []
+ end
+ end
+
+ def accept_api_auth?(action=action_name)
+ self.class.accept_api_auth.include?(action.to_sym)
+ end
+
# Returns the number of objects that should be displayed
# on the paginated list
def per_page_option
@@ -349,6 +384,30 @@
per_page
end
+ # Returns offset and limit used to retrieve objects
+ # for an API response based on offset, limit and page parameters
+ def api_offset_and_limit(options=params)
+ if options[:offset].present?
+ offset = options[:offset].to_i
+ if offset < 0
+ offset = 0
+ end
+ end
+ limit = options[:limit].to_i
+ if limit < 1
+ limit = 25
+ elsif limit > 100
+ limit = 100
+ end
+ if offset.nil? && options[:page].present?
+ offset = (options[:page].to_i - 1) * limit
+ offset = 0 if offset < 0
+ end
+ offset ||= 0
+
+ [offset, limit]
+ end
+
# qvalues http header parser
# code taken from webrick
def parse_qvalues(value)
@@ -369,16 +428,25 @@
rescue
nil
end
-
+
# Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
end
-
+
def api_request?
%w(xml json).include? params[:format]
end
+ # Returns the API key present in the request
+ def api_key_from_request
+ if params[:key].present?
+ params[:key]
+ elsif request.headers["X-Redmine-API-Key"].present?
+ request.headers["X-Redmine-API-Key"]
+ end
+ end
+
# Renders a warning flash if obj has unsaved attachments
def render_attachment_warning_if_needed(obj)
flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
@@ -413,5 +481,37 @@
{ attribute => error }
end.to_json
end
-
+
+ # Renders API response on validation failure
+ def render_validation_errors(object)
+ options = { :status => :unprocessable_entity, :layout => false }
+ options.merge!(case params[:format]
+ when 'xml'; { :xml => object.errors }
+ when 'json'; { :json => {'errors' => object.errors} } # ActiveResource client compliance
+ else
+ raise "Unknown format #{params[:format]} in #render_validation_errors"
+ end
+ )
+ render options
+ end
+
+ # Overrides #default_template so that the api template
+ # is used automatically if it exists
+ def default_template(action_name = self.action_name)
+ if api_request?
+ begin
+ return self.view_paths.find_template(default_template_name(action_name), 'api')
+ rescue ::ActionView::MissingTemplate
+ # the api template was not found
+ # fallback to the default behaviour
+ end
+ end
+ super
+ end
+
+ # Overrides #pick_layout so that #render with no arguments
+ # doesn't use the layout for api requests
+ def pick_layout(*args)
+ api_request? ? nil : super
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/attachments_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/attachments_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/attachments_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
# Redmine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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.
@@ -19,9 +19,9 @@
before_filter :find_project
before_filter :file_readable, :read_authorize, :except => :destroy
before_filter :delete_authorize, :only => :destroy
-
+
verify :method => :post, :only => :destroy
-
+
def show
if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read
@@ -33,19 +33,19 @@
download
end
end
-
+
def download
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end
-
+
# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
- :type => detect_content_type(@attachment),
+ :type => detect_content_type(@attachment),
:disposition => (@attachment.image? ? 'inline' : 'attachment')
-
+
end
-
+
def destroy
# Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment)
@@ -53,7 +53,7 @@
rescue ::ActionController::RedirectBackError
redirect_to :controller => 'projects', :action => 'show', :id => @project
end
-
+
private
def find_project
@attachment = Attachment.find(params[:id])
@@ -63,20 +63,20 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
# Checks that the file exists and is readable
def file_readable
@attachment.readable? ? true : render_404
end
-
+
def read_authorize
@attachment.visible? ? true : deny_access
end
-
+
def delete_authorize
@attachment.deletable? ? true : deny_access
end
-
+
def detect_content_type(attachment)
content_type = attachment.content_type
if content_type.blank?
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/auto_completes_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/auto_completes_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/auto_completes_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -4,12 +4,14 @@
def issues
@issues = []
q = params[:q].to_s
+ query = (params[:scope] == "all" && Setting.cross_project_issue_relations?) ? Issue : @project.issues
if q.match(/^\d+$/)
- @issues << @project.issues.visible.find_by_id(q.to_i)
+ @issues << query.visible.find_by_id(q.to_i)
end
unless q.blank?
- @issues += @project.issues.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
+ @issues += query.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
end
+ @issues.compact!
render :layout => false
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/boards_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/boards_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/boards_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -18,7 +18,7 @@
class BoardsController < ApplicationController
default_search_scope :messages
before_filter :find_project, :find_board_if_available, :authorize
- accept_key_auth :index, :show
+ accept_rss_auth :index, :show
helper :messages
include MessagesHelper
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/calendars_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/calendars_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/calendars_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class CalendarsController < ApplicationController
menu_item :calendar
before_filter :find_optional_project
@@ -36,9 +53,4 @@
render :action => 'show', :layout => false if request.xhr?
end
-
- def update
- show
- end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/context_menus_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/context_menus_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/context_menus_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,8 +1,10 @@
class ContextMenusController < ApplicationController
helper :watchers
+ helper :issues
def issues
- @issues = Issue.find_all_by_id(params[:ids], :include => :project)
+ @issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project)
+
if (@issues.size == 1)
@issue = @issues.first
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@@ -39,5 +41,18 @@
render :layout => false
end
-
+
+ def time_entries
+ @time_entries = TimeEntry.all(
+ :conditions => {:id => params[:ids]}, :include => :project)
+ @projects = @time_entries.collect(&:project).compact.uniq
+ @project = @projects.first if @projects.size == 1
+ @activities = TimeEntryActivity.shared.active
+ @can = {:edit => User.current.allowed_to?(:log_time, @projects),
+ :update => User.current.allowed_to?(:log_time, @projects),
+ :delete => User.current.allowed_to?(:log_time, @projects)
+ }
+ @back = back_url
+ render :layout => false
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/custom_fields_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/custom_fields_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/custom_fields_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -38,8 +38,9 @@
flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'index', :tab => @custom_field.class.name
+ else
+ @trackers = Tracker.find(:all, :order => 'position')
end
- @trackers = Tracker.find(:all, :order => 'position')
end
def edit
@@ -48,8 +49,9 @@
flash[:notice] = l(:notice_successful_update)
call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'index', :tab => @custom_field.class.name
+ else
+ @trackers = Tracker.find(:all, :order => 'position')
end
- @trackers = Tracker.find(:all, :order => 'position')
end
def destroy
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/enumerations_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/enumerations_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/enumerations_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -75,10 +75,12 @@
# No associated objects
@enumeration.destroy
redirect_to :action => 'index'
+ return
elsif params[:reassign_to_id]
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
@enumeration.destroy(reassign_to)
redirect_to :action => 'index'
+ return
end
end
@enumerations = @enumeration.class.find(:all) - [@enumeration]
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/files_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/files_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/files_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -13,7 +13,7 @@
'created_on' => "#{Attachment.table_name}.created_on",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
-
+
@containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)]
@containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
render :layout => !request.xhr?
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/gantts_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/gantts_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/gantts_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class GanttsController < ApplicationController
menu_item :gantt
before_filter :find_optional_project
@@ -28,9 +45,4 @@
format.pdf { send_data(@gantt.to_pdf, :type => 'application/pdf', :filename => "#{basename}.pdf") }
end
end
-
- def update
- show
- end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/groups_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/groups_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/groups_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -132,7 +132,7 @@
def autocomplete_for_user
@group = Group.find(params[:id])
- @users = User.active.like(params[:q]).find(:all, :limit => 100) - @group.users
+ @users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100)
render :layout => false
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/issue_categories_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/issue_categories_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/issue_categories_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -65,10 +65,12 @@
# No issue assigned to this category
@category.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
+ return
elsif params[:todo]
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) if params[:todo] == 'reassign'
@category.destroy(reassign_to)
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
+ return
end
@categories = @project.issue_categories - [@category]
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/issue_moves_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/issue_moves_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/issue_moves_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -2,7 +2,7 @@
default_search_scope :issues
before_filter :find_issues, :check_project_uniqueness
before_filter :authorize
-
+
def new
prepare_for_issue_move
render :layout => false if request.xhr?
@@ -48,7 +48,7 @@
@copy = params[:copy_options] && params[:copy_options][:copy]
@allowed_projects = Issue.allowed_target_projects_on_move
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
- @target_project ||= @project
+ @target_project ||= @project
@trackers = @target_project.trackers
@available_statuses = Workflow.available_statuses(@project)
@notes = params[:notes]
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/issue_relations_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/issue_relations_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/issue_relations_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,4 +1,4 @@
-# redMine - project management software
+# Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js do
+ @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
render :update do |page|
page.replace_html "relations", :partial => 'issues/relations'
if @relation.errors.empty?
@@ -47,7 +48,10 @@
end
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
- format.js { render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'} }
+ format.js {
+ @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
+ render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'}
+ }
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/issues_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/issues_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/issues_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
# Redmine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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.
@@ -18,7 +18,7 @@
class IssuesController < ApplicationController
menu_item :new_issue, :only => [:new, :create]
default_search_scope :issues
-
+
before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy]
before_filter :check_project_uniqueness, :only => [:move, :perform_move]
@@ -27,13 +27,14 @@
before_filter :find_optional_project, :only => [:index]
before_filter :check_for_default_issue_status, :only => [:new, :create]
before_filter :build_new_issue_from_params, :only => [:new, :create]
- accept_key_auth :index, :show, :create, :update, :destroy
+ accept_rss_auth :index, :show
+ accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
-
+
helper :journals
helper :projects
- include ProjectsHelper
+ include ProjectsHelper
helper :custom_fields
include CustomFieldsHelper
helper :issue_relations
@@ -44,6 +45,8 @@
include AttachmentsHelper
helper :queries
include QueriesHelper
+ helper :repositories
+ include RepositoriesHelper
helper :sort
include SortHelper
include IssuesHelper
@@ -58,34 +61,36 @@
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed }
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
-
+
def index
retrieve_query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns)
-
+
if @query.valid?
- limit = case params[:format]
+ case params[:format]
when 'csv', 'pdf'
- Setting.issues_export_limit.to_i
+ @limit = Setting.issues_export_limit.to_i
when 'atom'
- Setting.feeds_limit.to_i
+ @limit = Setting.feeds_limit.to_i
+ when 'xml', 'json'
+ @offset, @limit = api_offset_and_limit
else
- per_page_option
+ @limit = per_page_option
end
-
+
@issue_count = @query.issue_count
- @issue_pages = Paginator.new self, @issue_count, limit, params['page']
+ @issue_pages = Paginator.new self, @issue_count, @limit, params['page']
+ @offset ||= @issue_pages.current.offset
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
- :order => sort_clause,
- :offset => @issue_pages.current.offset,
- :limit => limit)
+ :order => sort_clause,
+ :offset => @offset,
+ :limit => @limit)
@issue_count_by_group = @query.issue_count_by_group
-
+
respond_to do |format|
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
- format.xml { render :layout => false }
- format.json { render :text => @issues.to_json, :layout => false }
+ format.api
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
@@ -97,21 +102,25 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
def show
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
@journals.each_with_index {|j,i| j.indice = i+1}
@journals.reverse! if User.current.wants_comments_in_reverse_order?
- @changesets = @issue.changesets.visible.all
- @changesets.reverse! if User.current.wants_comments_in_reverse_order?
+
+ if User.current.allowed_to?(:view_changesets, @project)
+ @changesets = @issue.changesets.visible.all
+ @changesets.reverse! if User.current.wants_comments_in_reverse_order?
+ end
+
+ @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.all
- @time_entry = TimeEntry.new
+ @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
respond_to do |format|
format.html { render :template => 'issues/show.rhtml' }
- format.xml { render :layout => false }
- format.json { render :text => @issue.to_json, :layout => false }
+ format.api
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
end
@@ -138,19 +147,17 @@
redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
{ :action => 'show', :id => @issue })
}
- format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
- format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
+ format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
end
return
else
respond_to do |format|
format.html { render :action => 'new' }
- format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
- format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
+ format.api { render_validation_errors(@issue) }
end
end
end
-
+
def edit
update_issue_from_params
@@ -171,8 +178,7 @@
respond_to do |format|
format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
- format.xml { head :ok }
- format.json { head :ok }
+ format.api { head :ok }
end
else
render_attachment_warning_if_needed(@issue)
@@ -181,8 +187,7 @@
respond_to do |format|
format.html { render :action => 'edit' }
- format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
- format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
+ format.api { render_validation_errors(@issue) }
end
end
end
@@ -214,7 +219,7 @@
set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
end
-
+
def destroy
@hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
if @hours > 0
@@ -232,35 +237,44 @@
TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
end
else
- unless params[:format] == 'xml' || params[:format] == 'json'
- # display the destroy form if it's a user request
- return
- end
+ # display the destroy form if it's a user request
+ return unless api_request?
end
end
- @issues.each(&:destroy)
+ @issues.each do |issue|
+ begin
+ issue.reload.destroy
+ rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
+ # nothing to do, issue was already deleted (eg. by a parent)
+ end
+ end
respond_to do |format|
format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
- format.xml { head :ok }
- format.json { head :ok }
+ format.api { head :ok }
end
end
private
def find_issue
+ # Issue.visible.find(...) can not be used to redirect user to the login form
+ # if the issue actually exists but requires authentication
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
+ unless @issue.visible?
+ deny_access
+ return
+ end
@project = @issue.project
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
def find_project
project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
@project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
# Used by #edit and #update to set some common instance variables
# from the params
# TODO: Refactor, not everything in here is needed by #edit
@@ -268,9 +282,9 @@
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.all
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
- @time_entry = TimeEntry.new
+ @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry]
-
+
@notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil)
@issue.init_journal(User.current, @notes)
@issue.safe_attributes = params[:issue]
@@ -286,8 +300,9 @@
else
@issue = @project.issues.visible.find(params[:id])
end
-
+
@issue.project = @project
+ @issue.author = User.current
# Tracker must be set before custom field values
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
if @issue.tracker.nil?
@@ -301,7 +316,6 @@
@issue.watcher_user_ids = params[:issue]['watcher_user_ids']
end
end
- @issue.author = User.current
@priorities = IssuePriority.all
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/journals_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/journals_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/journals_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -16,12 +16,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class JournalsController < ApplicationController
- before_filter :find_journal, :only => [:edit]
+ before_filter :find_journal, :only => [:edit, :diff]
before_filter :find_issue, :only => [:new]
before_filter :find_optional_project, :only => [:index]
- accept_key_auth :index
-
+ before_filter :authorize, :only => [:new, :edit, :diff]
+ accept_rss_auth :index
+ menu_item :issues
+
helper :issues
+ helper :custom_fields
helper :queries
include QueriesHelper
helper :sort
@@ -42,6 +45,17 @@
render_404
end
+ def diff
+ @issue = @journal.issue
+ if params[:detail_id].present?
+ @detail = @journal.details.find_by_id(params[:detail_id])
+ else
+ @detail = @journal.details.detect {|d| d.prop_key == 'description'}
+ end
+ (render_404; return false) unless @issue && @detail
+ @diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
+ end
+
def new
journal = Journal.find(params[:journal_id]) if params[:journal_id]
if journal
@@ -66,6 +80,7 @@
end
def edit
+ (render_403; return false) unless @journal.editable_by?(User.current)
if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank?
@@ -74,13 +89,21 @@
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id }
format.js { render :action => 'update' }
end
+ else
+ respond_to do |format|
+ format.html {
+ # TODO: implement non-JS journal update
+ render :nothing => true
+ }
+ format.js
+ end
end
end
-private
+ private
+
def find_journal
@journal = Journal.find(params[:id])
- (render_403; return false) unless @journal.editable_by?(User.current)
@project = @journal.journalized.project
rescue ActiveRecord::RecordNotFound
render_404
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/mail_handler_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/mail_handler_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/mail_handler_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,27 +1,27 @@
-# redMine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MailHandlerController < ActionController::Base
before_filter :check_credential
-
+
verify :method => :post,
:only => :index,
:render => { :nothing => true, :status => 405 }
-
+
# Submits an incoming email to MailHandler
def index
options = params.dup
@@ -32,9 +32,9 @@
render :nothing => true, :status => :unprocessable_entity
end
end
-
+
private
-
+
def check_credential
User.current = nil
unless Setting.mail_handler_api_enabled? && params[:key].to_s == Setting.mail_handler_api_key
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/my_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/my_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/my_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -19,6 +19,7 @@
before_filter :require_login
helper :issues
+ helper :users
helper :custom_fields
BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
@@ -53,21 +54,18 @@
@user = User.current
@pref = @user.pref
if request.post?
- @user.attributes = params[:user]
- @user.mail_notification = params[:notification_option] || 'only_my_events'
+ @user.safe_attributes = params[:user]
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
if @user.save
@user.pref.save
- @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
+ @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
set_language_if_valid @user.language
flash[:notice] = l(:notice_account_updated)
redirect_to :action => 'account'
return
end
end
- @notification_options = @user.valid_notification_options
- @notification_option = @user.mail_notification #? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected')
end
# Manage user's password
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/news_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/news_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/news_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -23,18 +23,32 @@
before_filter :find_project, :only => [:new, :create]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => :index
- accept_key_auth :index
+ accept_rss_auth :index
+ accept_api_auth :index
+
+ helper :watchers
def index
- @news_pages, @newss = paginate :news,
- :per_page => 10,
- :conditions => Project.allowed_to_condition(User.current, :view_news, :project => @project),
- :include => [:author, :project],
- :order => "#{News.table_name}.created_on DESC"
+ case params[:format]
+ when 'xml', 'json'
+ @offset, @limit = api_offset_and_limit
+ else
+ @limit = 10
+ end
+
+ scope = @project ? @project.news.visible : News.visible
+
+ @news_count = scope.count
+ @news_pages = Paginator.new self, @news_count, @limit, params['page']
+ @offset ||= @news_pages.current.offset
+ @newss = scope.all(:include => [:author, :project],
+ :order => "#{News.table_name}.created_on DESC",
+ :offset => @offset,
+ :limit => @limit)
+
respond_to do |format|
format.html { render :layout => false if request.xhr? }
- format.xml { render :xml => @newss.to_xml }
- format.json { render :json => @newss.to_json }
+ format.api
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/previews_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/previews_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/previews_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class PreviewsController < ApplicationController
before_filter :find_project
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/projects_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/projects_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/projects_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -24,7 +24,8 @@
before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
before_filter :authorize_global, :only => [:new, :create]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
- accept_key_auth :index
+ accept_rss_auth :index
+ accept_api_auth :index, :show, :create, :update, :destroy
after_filter :only => [:create, :edit, :update, :archive, :unarchive, :destroy] do |controller|
if controller.request.post?
@@ -32,9 +33,6 @@
end
end
- # TODO: convert to PUT only
- verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
-
helper :sort
include SortHelper
helper :custom_fields
@@ -52,8 +50,10 @@
format.html {
@projects = Project.visible.find(:all, :order => 'lft')
}
- format.xml {
- @projects = Project.visible.find(:all, :order => 'lft')
+ format.api {
+ @offset, @limit = api_offset_and_limit
+ @project_count = Project.visible.count
+ @projects = Project.visible.all(:offset => @offset, :limit => @limit, :order => 'lft')
}
format.atom {
projects = Project.visible.find(:all, :order => 'created_on DESC',
@@ -67,19 +67,15 @@
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all
@project = Project.new(params[:project])
-
- @project.identifier = Project.next_identifier if Setting.sequential_project_identifiers?
- @project.trackers = Tracker.all
- @project.is_public = Setting.default_projects_public?
- @project.enabled_module_names = Setting.default_projects_modules
end
+ verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all
- @project = Project.new(params[:project])
+ @project = Project.new
+ @project.safe_attributes = params[:project]
- @project.enabled_module_names = params[:enabled_modules]
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
@@ -93,12 +89,12 @@
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'projects', :action => 'settings', :id => @project
}
- format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
+ format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
end
else
respond_to do |format|
format.html { render :action => 'new' }
- format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
+ format.api { render_validation_errors(@project) }
end
end
@@ -120,18 +116,18 @@
end
else
Mailer.with_deliveries(params[:notifications] == '1') do
- @project = Project.new(params[:project])
- @project.enabled_module_names = params[:enabled_modules]
+ @project = Project.new
+ @project.safe_attributes = params[:project]
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
flash[:notice] = l(:notice_successful_create)
- redirect_to :controller => 'projects', :action => 'settings'
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
elsif !@project.new_record?
# Project was created
# But some objects were not copied due to validation failures
# (eg. issues from disabled trackers)
# TODO: inform about that
- redirect_to :controller => 'projects', :action => 'settings'
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
end
end
end
@@ -147,7 +143,7 @@
end
@users_by_role = @project.users_by_role
- @subprojects = @project.children.visible
+ @subprojects = @project.children.visible.all
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = @project.rolled_up_trackers
@@ -160,16 +156,15 @@
:include => [:project, :status, :tracker],
:conditions => cond)
- TimeEntry.visible_by(User.current) do
- @total_hours = TimeEntry.sum(:hours,
- :include => :project,
- :conditions => cond).to_f
+ if User.current.allowed_to?(:view_time_entries, @project)
+ @total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f
end
+
@key = User.current.rss_key
respond_to do |format|
format.html
- format.xml
+ format.api
end
end
@@ -185,8 +180,10 @@
def edit
end
+ # TODO: convert to PUT only
+ verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update
- @project.attributes = params[:project]
+ @project.safe_attributes = params[:project]
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
respond_to do |format|
@@ -194,7 +191,7 @@
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project
}
- format.xml { head :ok }
+ format.api { head :ok }
end
else
respond_to do |format|
@@ -202,13 +199,14 @@
settings
render :action => 'settings'
}
- format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
+ format.api { render_validation_errors(@project) }
end
end
end
-
+
+ verify :method => :post, :only => :modules, :render => {:nothing => true, :status => :method_not_allowed }
def modules
- @project.enabled_module_names = params[:enabled_modules]
+ @project.enabled_module_names = params[:enabled_module_names]
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project, :tab => 'modules'
end
@@ -233,11 +231,11 @@
if request.get?
# display confirmation view
else
- if params[:format] == 'xml' || params[:confirm]
+ if api_request? || params[:confirm]
@project_to_destroy.destroy
respond_to do |format|
format.html { redirect_to :controller => 'admin', :action => 'projects' }
- format.xml { head :ok }
+ format.api { head :ok }
end
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/queries_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/queries_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/queries_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -25,11 +25,12 @@
@query.project = params[:query_is_for_all] ? nil : @project
@query.user = User.current
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
+
+ @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
+ @query.group_by ||= params[:group_by]
+ @query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
- @query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields]
- @query.group_by ||= params[:group_by]
-
if request.post? && params[:confirm] && @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query
@@ -41,10 +42,12 @@
def edit
if request.post?
@query.filters = {}
- @query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields]
+ @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.attributes = params[:query]
@query.project = nil if params[:query_is_for_all]
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
+ @query.group_by ||= params[:group_by]
+ @query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
if @query.save
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/repositories_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/repositories_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/repositories_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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.
@@ -26,33 +26,45 @@
menu_item :repository
menu_item :settings, :only => :edit
default_search_scope :changesets
-
+
before_filter :find_repository, :except => :edit
before_filter :find_project, :only => :edit
before_filter :authorize
- accept_key_auth :revisions
-
+ accept_rss_auth :revisions
+
rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
-
+
def edit
@repository = @project.repository
- if !@repository
+ if !@repository && !params[:repository_scm].blank?
@repository = Repository.factory(params[:repository_scm])
@repository.project = @project if @repository
end
if request.post? && @repository
- @repository.attributes = params[:repository]
+ p1 = params[:repository]
+ p = {}
+ p_extra = {}
+ p1.each do |k, v|
+ if k =~ /^extra_/
+ p_extra[k] = v
+ else
+ p[k] = v
+ end
+ end
+ @repository.attributes = p
+ @repository.merge_extra_info(p_extra)
@repository.save
end
render(:update) do |page|
- page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'
+ page.replace_html "tab-content-repository",
+ :partial => 'projects/settings/repository'
if @repository && !@project.repository
- @project.reload #needed to reload association
+ @project.reload # needed to reload association
page.replace_html "main-menu", render_main_menu(@project)
end
end
end
-
+
def committers
@committers = @repository.committers
@users = @project.users
@@ -67,16 +79,20 @@
redirect_to :action => 'committers', :id => @project
end
end
-
+
def destroy
@repository.destroy
- redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
+ redirect_to :controller => 'projects',
+ :action => 'settings',
+ :id => @project,
+ :tab => 'repository'
end
-
- def show
+
+ def show
@repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
@entries = @repository.entries(@path, @rev)
+ @changeset = @repository.find_changeset_by_name(@rev)
if request.xhr?
@entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
else
@@ -88,30 +104,31 @@
end
alias_method :browse, :show
-
+
def changes
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
@changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
@properties = @repository.properties(@path, @rev)
+ @changeset = @repository.find_changeset_by_name(@rev)
end
-
+
def revisions
@changeset_count = @repository.changesets.count
@changeset_pages = Paginator.new self, @changeset_count,
- per_page_option,
- params['page']
+ per_page_option,
+ params['page']
@changesets = @repository.changesets.find(:all,
- :limit => @changeset_pages.items_per_page,
- :offset => @changeset_pages.current.offset,
- :include => [:user, :repository])
+ :limit => @changeset_pages.items_per_page,
+ :offset => @changeset_pages.current.offset,
+ :include => [:user, :repository])
respond_to do |format|
format.html { render :layout => false if request.xhr? }
format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
end
end
-
+
def entry
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
@@ -121,24 +138,46 @@
@content = @repository.cat(@path, @rev)
(show_error_not_found; return) unless @content
- if 'raw' == params[:format] || @content.is_binary_data? || (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte)
+ if 'raw' == params[:format] ||
+ (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
+ ! is_entry_text_data?(@content, @path)
# Force the download
- send_data @content, :filename => @path.split('/').last
+ send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
+ send_type = Redmine::MimeType.of(@path)
+ send_opt[:type] = send_type.to_s if send_type
+ send_data @content, send_opt
else
# Prevent empty lines when displaying a file with Windows style eol
+ # TODO: UTF-16
+ # Is this needs? AttachmentsController reads file simply.
@content.gsub!("\r\n", "\n")
- end
+ @changeset = @repository.find_changeset_by_name(@rev)
+ end
end
-
+
+ def is_entry_text_data?(ent, path)
+ # UTF-16 contains "\x00".
+ # It is very strict that file contains less than 30% of ascii symbols
+ # in non Western Europe.
+ return true if Redmine::MimeType.is_type?('text', path)
+ # Ruby 1.8.6 has a bug of integer divisions.
+ # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
+ return false if ent.is_binary_data?
+ true
+ end
+ private :is_entry_text_data?
+
def annotate
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
-
+
@annotate = @repository.scm.annotate(@path, @rev)
(render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
+ @changeset = @repository.find_changeset_by_name(@rev)
end
-
+
def revision
+ raise ChangesetNotFound if @rev.blank?
@changeset = @repository.find_changeset_by_name(@rev)
raise ChangesetNotFound unless @changeset
@@ -149,7 +188,7 @@
rescue ChangesetNotFound
show_error_not_found
end
-
+
def diff
if params[:format] == 'diff'
@diff = @repository.diff(@path, @rev, @rev_to)
@@ -162,26 +201,30 @@
else
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
-
+
# Save diff type as user preference
if User.current.logged? && @diff_type != User.current.pref[:diff_type]
User.current.pref[:diff_type] = @diff_type
User.current.preference.save
end
-
- @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
+ @cache_key = "repositories/diff/#{@repository.id}/" +
+ Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
unless read_fragment(@cache_key)
@diff = @repository.diff(@path, @rev, @rev_to)
show_error_not_found unless @diff
end
+
+ @changeset = @repository.find_changeset_by_name(@rev)
+ @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
+ @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
end
end
-
- def stats
+
+ def stats
end
-
+
def graph
- data = nil
+ data = nil
case params[:graph]
when "commits_per_month"
data = graph_commits_per_month(@repository)
@@ -195,8 +238,11 @@
render_404
end
end
-
-private
+
+ private
+
+ REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
+
def find_repository
@project = Project.find(params[:id])
@repository = @project.repository
@@ -205,6 +251,12 @@
@path ||= ''
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
@rev_to = params[:rev_to]
+
+ unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
+ if @repository.branches.blank?
+ raise InvalidRevisionParam
+ end
+ end
rescue ActiveRecord::RecordNotFound
render_404
rescue InvalidRevisionParam
@@ -212,29 +264,33 @@
end
def show_error_not_found
- render_error l(:error_scm_not_found)
+ render_error :message => l(:error_scm_not_found), :status => 404
end
-
+
# Handler for Redmine::Scm::Adapters::CommandFailed exception
def show_error_command_failed(exception)
render_error l(:error_scm_command_failed, exception.message)
end
-
+
def graph_commits_per_month(repository)
@date_to = Date.today
@date_from = @date_to << 11
@date_from = Date.civil(@date_from.year, @date_from.month, 1)
- commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
+ commits_by_day = repository.changesets.count(
+ :all, :group => :commit_date,
+ :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
commits_by_month = [0] * 12
commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
- changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
+ changes_by_day = repository.changes.count(
+ :all, :group => :commit_date,
+ :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
changes_by_month = [0] * 12
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
-
+
fields = []
12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
-
+
graph = SVG::Graph::Bar.new(
:height => 300,
:width => 800,
@@ -246,7 +302,7 @@
:graph_title => l(:label_commits_per_month),
:show_graph_title => true
)
-
+
graph.add_data(
:data => commits_by_month[0..11].reverse,
:title => l(:label_revision_plural)
@@ -256,7 +312,7 @@
:data => changes_by_month[0..11].reverse,
:title => l(:label_change_plural)
)
-
+
graph.burn
end
@@ -266,18 +322,18 @@
changes_by_author = repository.changes.count(:all, :group => :committer)
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
-
+
fields = commits_by_author.collect {|r| r.first}
commits_data = commits_by_author.collect {|r| r.last}
changes_data = commits_by_author.collect {|r| h[r.first] || 0}
-
+
fields = fields + [""]*(10 - fields.length) if fields.length<10
commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
-
+
# Remove email adress in usernames
fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
-
+
graph = SVG::Graph::BarHorizontal.new(
:height => 400,
:width => 800,
@@ -289,22 +345,18 @@
:graph_title => l(:label_commits_per_author),
:show_graph_title => true
)
-
graph.add_data(
:data => commits_data,
:title => l(:label_revision_plural)
)
-
graph.add_data(
:data => changes_data,
:title => l(:label_change_plural)
)
-
graph.burn
end
+end
-end
-
class Date
def months_ago(date = Date.today)
(date.year - self.year)*12 + (date.month - self.month)
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/roles_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/roles_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/roles_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -38,9 +38,10 @@
end
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'index'
+ else
+ @permissions = @role.setable_permissions
+ @roles = Role.find :all, :order => 'builtin, position'
end
- @permissions = @role.setable_permissions
- @roles = Role.find :all, :order => 'builtin, position'
end
def edit
@@ -48,8 +49,9 @@
if request.post? and @role.update_attributes(params[:role])
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index'
+ else
+ @permissions = @role.setable_permissions
end
- @permissions = @role.setable_permissions
end
def destroy
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/search_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/search_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/search_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -24,8 +24,8 @@
def index
@question = params[:q] || ""
@question.strip!
- @all_words = params[:all_words] || (params[:submit] ? false : true)
- @titles_only = !params[:titles_only].nil?
+ @all_words = params[:all_words] ? params[:all_words].present? : true
+ @titles_only = params[:titles_only] ? params[:titles_only].present? : false
projects_to_search =
case params[:scope]
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/settings_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/settings_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/settings_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -17,7 +17,7 @@
class SettingsController < ApplicationController
layout 'admin'
-
+
before_filter :require_admin
def index
@@ -36,14 +36,16 @@
end
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :tab => params[:tab]
- return
+ else
+ @options = {}
+ @options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
+ @deliveries = ActionMailer::Base.perform_deliveries
+
+ @guessed_host_and_path = request.host_with_port.dup
+ @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
+
+ Redmine::Themes.rescan
end
- @options = {}
- @options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
- @deliveries = ActionMailer::Base.perform_deliveries
-
- @guessed_host_and_path = request.host_with_port.dup
- @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
end
def plugin
@@ -52,9 +54,10 @@
Setting["plugin_#{@plugin.id}"] = params[:settings]
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'plugin', :id => @plugin.id
+ else
+ @partial = @plugin.settings[:partial]
+ @settings = Setting["plugin_#{@plugin.id}"]
end
- @partial = @plugin.settings[:partial]
- @settings = Setting["plugin_#{@plugin.id}"]
rescue Redmine::PluginNotFound
render_404
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/timelog_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/timelog_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/timelog_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -18,10 +18,13 @@
class TimelogController < ApplicationController
menu_item :issues
before_filter :find_project, :only => [:new, :create]
- before_filter :find_time_entry, :only => [:edit, :update, :destroy]
+ before_filter :find_time_entry, :only => [:show, :edit, :update]
+ before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => [:index]
-
+ accept_rss_auth :index
+ accept_api_auth :index, :show, :create, :update, :destroy
+
helper :sort
include SortHelper
helper :issues
@@ -39,50 +42,64 @@
'hours' => 'hours'
cond = ARCondition.new
- if @project.nil?
- cond << Project.allowed_to_condition(User.current, :view_time_entries)
- elsif @issue.nil?
+ if @issue
+ cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
+ elsif @project
cond << @project.project_condition(Setting.display_subprojects_issues?)
- else
- cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
end
retrieve_date_range
cond << ['spent_on BETWEEN ? AND ?', @from, @to]
- TimeEntry.visible_by(User.current) do
- respond_to do |format|
- format.html {
- # Paginate results
- @entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions)
- @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => sort_clause,
- :limit => @entry_pages.items_per_page,
- :offset => @entry_pages.current.offset)
- @total_hours = TimeEntry.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
+ respond_to do |format|
+ format.html {
+ # Paginate results
+ @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
+ @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => sort_clause,
+ :limit => @entry_pages.items_per_page,
+ :offset => @entry_pages.current.offset)
+ @total_hours = TimeEntry.visible.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
- render :layout => !request.xhr?
- }
- format.atom {
- entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => "#{TimeEntry.table_name}.created_on DESC",
- :limit => Setting.feeds_limit.to_i)
- render_feed(entries, :title => l(:label_spent_time))
- }
- format.csv {
- # Export all entries
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
- :conditions => cond.conditions,
- :order => sort_clause)
- send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
- }
- end
+ render :layout => !request.xhr?
+ }
+ format.api {
+ @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
+ @offset, @limit = api_offset_and_limit
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => sort_clause,
+ :limit => @limit,
+ :offset => @offset)
+ }
+ format.atom {
+ entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => "#{TimeEntry.table_name}.created_on DESC",
+ :limit => Setting.feeds_limit.to_i)
+ render_feed(entries, :title => l(:label_spent_time))
+ }
+ format.csv {
+ # Export all entries
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
+ :conditions => cond.conditions,
+ :order => sort_clause)
+ send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
+ }
+ end
+ end
+
+ def show
+ respond_to do |format|
+ # TODO: Implement html response
+ format.html { render :nothing => true, :status => 406 }
+ format.api
end
end
@@ -102,10 +119,18 @@
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
- flash[:notice] = l(:notice_successful_update)
- redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_update)
+ redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ }
+ format.api { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
+ end
else
- render :action => 'edit'
+ respond_to do |format|
+ format.html { render :action => 'edit' }
+ format.api { render_validation_errors(@time_entry) }
+ end
end
end
@@ -122,23 +147,70 @@
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
- flash[:notice] = l(:notice_successful_update)
- redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_update)
+ redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ }
+ format.api { head :ok }
+ end
else
- render :action => 'edit'
+ respond_to do |format|
+ format.html { render :action => 'edit' }
+ format.api { render_validation_errors(@time_entry) }
+ end
end
end
+ def bulk_edit
+ @available_activities = TimeEntryActivity.shared.active
+ @custom_fields = TimeEntry.first.available_custom_fields
+ end
+
+ def bulk_update
+ attributes = parse_params_for_bulk_time_entry_attributes(params)
+
+ unsaved_time_entry_ids = []
+ @time_entries.each do |time_entry|
+ time_entry.reload
+ time_entry.attributes = attributes
+ call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
+ unless time_entry.save
+ # Keep unsaved time_entry ids to display them in flash error
+ unsaved_time_entry_ids << time_entry.id
+ end
+ end
+ set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
+ redirect_back_or_default({:controller => 'timelog', :action => 'index', :project_id => @projects.first})
+ end
+
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy
- if @time_entry.destroy && @time_entry.destroyed?
- flash[:notice] = l(:notice_successful_delete)
- else
- flash[:error] = l(:notice_unable_delete_time_entry)
+ @time_entries.each do |t|
+ begin
+ unless t.destroy && t.destroyed?
+ respond_to do |format|
+ format.html {
+ flash[:error] = l(:notice_unable_delete_time_entry)
+ redirect_to :back
+ }
+ format.api { render_validation_errors(t) }
+ end
+ return
+ end
+ rescue ::ActionController::RedirectBackError
+ redirect_to :action => 'index', :project_id => @projects.first
+ return
+ end
end
- redirect_to :back
- rescue ::ActionController::RedirectBackError
- redirect_to :action => 'index', :project_id => @time_entry.project
+
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_delete)
+ redirect_back_or_default(:action => 'index', :project_id => @projects.first)
+ }
+ format.api { head :ok }
+ end
end
private
@@ -153,12 +225,32 @@
render_404
end
+ def find_time_entries
+ @time_entries = TimeEntry.find_all_by_id(params[:id] || params[:ids])
+ raise ActiveRecord::RecordNotFound if @time_entries.empty?
+ @projects = @time_entries.collect(&:project).compact.uniq
+ @project = @projects.first if @projects.size == 1
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+
+ def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids)
+ if unsaved_time_entry_ids.empty?
+ flash[:notice] = l(:notice_successful_update) unless time_entries.empty?
+ else
+ flash[:error] = l(:notice_failed_to_save_time_entries,
+ :count => unsaved_time_entry_ids.size,
+ :total => time_entries.size,
+ :ids => '#' + unsaved_time_entry_ids.join(', #'))
+ end
+ end
+
def find_project
- if params[:issue_id]
- @issue = Issue.find(params[:issue_id])
+ if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
+ @issue = Issue.find(issue_id)
@project = @issue.project
- elsif params[:project_id]
- @project = Project.find(params[:project_id])
+ elsif (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
+ @project = Project.find(project_id)
else
render_404
return false
@@ -223,4 +315,10 @@
@to ||= (TimeEntry.latest_date_for_project(@project) || Date.today)
end
+ def parse_params_for_bulk_time_entry_attributes(params)
+ attributes = (params[:time_entry] || {}).reject {|k,v| v.blank?}
+ attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
+ attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
+ attributes
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/users_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/users_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/users_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -19,6 +19,8 @@
layout 'admin'
before_filter :require_admin, :except => :show
+ before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
+ accept_api_auth :index, :show, :create, :update, :destroy
helper :sort
include SortHelper
@@ -29,6 +31,16 @@
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
+ case params[:format]
+ when 'xml', 'json'
+ @offset, @limit = api_offset_and_limit
+ else
+ @limit = per_page_option
+ end
+
+ scope = User
+ scope = scope.in_group(params[:group_id].to_i) if params[:group_id].present?
+
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
@@ -37,23 +49,27 @@
c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name]
end
- @user_count = User.count(:conditions => c.conditions)
- @user_pages = Paginator.new self, @user_count,
- per_page_option,
- params['page']
- @users = User.find :all,:order => sort_clause,
+ @user_count = scope.count(:conditions => c.conditions)
+ @user_pages = Paginator.new self, @user_count, @limit, params['page']
+ @offset ||= @user_pages.current.offset
+ @users = scope.find :all,
+ :order => sort_clause,
:conditions => c.conditions,
- :limit => @user_pages.items_per_page,
- :offset => @user_pages.current.offset
+ :limit => @limit,
+ :offset => @offset
- render :layout => !request.xhr?
+ respond_to do |format|
+ format.html {
+ @groups = Group.all.sort
+ render :layout => !request.xhr?
+ }
+ format.api
+ end
end
def show
- @user = User.find(params[:id])
-
# show projects based on current user visibility
- @memberships = @user.memberships.all(:conditions => Project.visible_by(User.current))
+ @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current))
events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
@events_by_day = events.group_by(&:event_date)
@@ -64,104 +80,119 @@
return
end
end
- render :layout => 'base'
-
- rescue ActiveRecord::RecordNotFound
- render_404
+
+ respond_to do |format|
+ format.html { render :layout => 'base' }
+ format.api
+ end
end
def new
- @notification_options = User::MAIL_NOTIFICATION_OPTIONS
- @notification_option = Setting.default_notification_option
-
- @user = User.new(:language => Setting.default_language)
+ @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
@auth_sources = AuthSource.find(:all)
end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
- @notification_options = User::MAIL_NOTIFICATION_OPTIONS
- @notification_option = Setting.default_notification_option
-
- @user = User.new(params[:user])
+ @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
+ @user.safe_attributes = params[:user]
@user.admin = params[:user][:admin] || false
@user.login = params[:user][:login]
- @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
+ @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
# TODO: Similar to My#account
- @user.mail_notification = params[:notification_option] || 'only_my_events'
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
if @user.save
@user.pref.save
- @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
+ @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
- Mailer.deliver_account_information(@user, params[:password]) if params[:send_information]
- flash[:notice] = l(:notice_successful_create)
- redirect_to(params[:continue] ? {:controller => 'users', :action => 'new'} :
- {:controller => 'users', :action => 'edit', :id => @user})
- return
+ Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information]
+
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to(params[:continue] ?
+ {:controller => 'users', :action => 'new'} :
+ {:controller => 'users', :action => 'edit', :id => @user}
+ )
+ }
+ format.api { render :action => 'show', :status => :created, :location => user_url(@user) }
+ end
else
@auth_sources = AuthSource.find(:all)
- @notification_option = @user.mail_notification
+ # Clear password input
+ @user.password = @user.password_confirmation = nil
- render :action => 'new'
+ respond_to do |format|
+ format.html { render :action => 'new' }
+ format.api { render_validation_errors(@user) }
+ end
end
end
def edit
- @user = User.find(params[:id])
- @notification_options = @user.valid_notification_options
- @notification_option = @user.mail_notification
-
@auth_sources = AuthSource.find(:all)
@membership ||= Member.new
end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update
- @user = User.find(params[:id])
- @notification_options = @user.valid_notification_options
- @notification_option = @user.mail_notification
-
@user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login]
- if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
- @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
+ if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
+ @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation]
end
- @user.group_ids = params[:user][:group_ids] if params[:user][:group_ids]
- @user.attributes = params[:user]
+ @user.safe_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])
# TODO: Similar to My#account
- @user.mail_notification = params[:notification_option] || 'only_my_events'
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
if @user.save
@user.pref.save
- @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
+ @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
if was_activated
Mailer.deliver_account_activated(@user)
- elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil?
- Mailer.deliver_account_information(@user, params[:password])
+ elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
+ Mailer.deliver_account_information(@user, params[:user][:password])
end
- flash[:notice] = l(:notice_successful_update)
- redirect_to :back
+
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :back
+ }
+ format.api { head :ok }
+ end
else
@auth_sources = AuthSource.find(:all)
@membership ||= Member.new
+ # Clear password input
+ @user.password = @user.password_confirmation = nil
- render :action => :edit
+ respond_to do |format|
+ format.html { render :action => :edit }
+ format.api { render_validation_errors(@user) }
+ end
end
rescue ::ActionController::RedirectBackError
redirect_to :controller => 'users', :action => 'edit', :id => @user
end
+ verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
+ def destroy
+ @user.destroy
+ respond_to do |format|
+ format.html { redirect_to(users_url) }
+ format.api { head :ok }
+ end
+ end
+
def edit_membership
- @user = User.find(params[:id])
@membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
@membership.save if request.post?
respond_to do |format|
@@ -184,7 +215,6 @@
end
def destroy_membership
- @user = User.find(params[:id])
@membership = Member.find(params[:membership_id])
if request.post? && @membership.deletable?
@membership.destroy
@@ -194,4 +224,17 @@
format.js { render(:update) {|page| page.replace_html "tab-content-memberships", :partial => 'users/memberships'} }
end
end
+
+ private
+
+ def find_user
+ if params[:id] == 'current'
+ require_login || return
+ @user = User.current
+ else
+ @user = User.find(params[:id])
+ end
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/watchers_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/watchers_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/watchers_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -76,21 +76,13 @@
def set_watcher(user, watching)
@watched.set_watcher(user, watching)
- if params[:replace].present?
- if params[:replace].is_a? Array
- replace_ids = params[:replace]
- else
- replace_ids = [params[:replace]]
- end
- else
- replace_ids = ['watcher']
- end
respond_to do |format|
format.html { redirect_to :back }
format.js do
render(:update) do |page|
- replace_ids.each do |replace_id|
- page.replace_html replace_id, watcher_link(@watched, user, :replace => replace_ids)
+ c = watcher_css(@watched)
+ page.select(".#{c}").each do |item|
+ page.replace_html item, watcher_link(@watched, user)
end
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/wiki_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/wiki_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/wiki_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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.
@@ -34,23 +34,27 @@
class WikiController < ApplicationController
default_search_scope :wiki_pages
before_filter :find_wiki, :authorize
+ before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
-
- verify :method => :post, :only => [:protect], :redirect_to => { :action => :show }
helper :attachments
- include AttachmentsHelper
+ include AttachmentsHelper
helper :watchers
# List of pages, sorted alphabetically and by parent (hierarchy)
def index
- load_pages_grouped_by_date_without_content
+ load_pages_for_index
+ @pages_by_parent_id = @pages.group_by(&:parent_id)
+ end
+
+ # List of page, by last update
+ def date_index
+ load_pages_for_index
+ @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
end
# display a page (in editing mode if it doesn't exist)
def show
- page_title = params[:id]
- @page = @wiki.find_or_new_page(page_title)
if @page.new_record?
if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
edit
@@ -79,13 +83,12 @@
@editable = editable?
render :action => 'show'
end
-
+
# edit an existing page or a new one
def edit
- @page = @wiki.find_or_new_page(params[:id])
return render_403 unless editable?
@page.content = WikiContent.new(:page => @page) if @page.new_record?
-
+
@content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@@ -93,18 +96,14 @@
# To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version
- rescue ActiveRecord::StaleObjectError
- # Optimistic locking exception
- flash[:error] = l(:notice_locking_conflict)
end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
# Creates a new page or updates an existing one
def update
- @page = @wiki.find_or_new_page(params[:id])
return render_403 unless editable?
@page.content = WikiContent.new(:page => @page) if @page.new_record?
-
+
@content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@@ -125,11 +124,14 @@
render_attachment_warning_if_needed(@page)
call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
redirect_to :action => 'show', :project_id => @project, :id => @page.title
+ else
+ render :action => 'edit'
end
rescue ActiveRecord::StaleObjectError
# Optimistic locking exception
- flash[:error] = l(:notice_locking_conflict)
+ flash.now[:error] = l(:notice_locking_conflict)
+ render :action => 'edit'
end
# rename a page
@@ -143,7 +145,8 @@
redirect_to :action => 'show', :project_id => @project, :id => @page.title
end
end
-
+
+ verify :method => :post, :only => :protect, :redirect_to => { :action => :show }
def protect
@page.update_attribute :protected, params[:protected]
redirect_to :action => 'show', :project_id => @project, :id => @page.title
@@ -153,8 +156,8 @@
def history
@version_count = @page.content.versions.count
@version_pages = Paginator.new self, @version_count, per_page_option, params['p']
- # don't load text
- @versions = @page.content.versions.find :all,
+ # don't load text
+ @versions = @page.content.versions.find :all,
:select => "id, author_id, comments, updated_on, version",
:order => 'version DESC',
:limit => @version_pages.items_per_page + 1,
@@ -162,12 +165,12 @@
render :layout => false if request.xhr?
end
-
+
def diff
@diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff
end
-
+
def annotate
@annotate = @page.annotate(params[:version])
render_404 unless @annotate
@@ -178,7 +181,7 @@
# Children can be either set as root pages, removed or reassigned to another parent page
def destroy
return render_403 unless editable?
-
+
@descendants_count = @page.descendants.size
if @descendants_count > 0
case params[:todo]
@@ -214,10 +217,6 @@
end
end
- def date_index
- load_pages_grouped_by_date_without_content
- end
-
def preview
page = @wiki.find_page(params[:id])
# page is nil when previewing a new page
@@ -238,7 +237,7 @@
end
private
-
+
def find_wiki
@project = Project.find(params[:project_id])
@wiki = @project.wiki
@@ -246,13 +245,27 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
+ # Finds the requested page or a new page if it doesn't exist
+ def find_existing_or_new_page
+ @page = @wiki.find_or_new_page(params[:id])
+ if @wiki.page_found_with_redirect?
+ redirect_to params.update(:id => @page.title)
+ end
+ end
+
# Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page
@page = @wiki.find_page(params[:id])
- render_404 if @page.nil?
+ if @page.nil?
+ render_404
+ return
+ end
+ if @wiki.page_found_with_redirect?
+ redirect_to params.update(:id => @page.title)
+ end
end
-
+
# Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page)
page.editable_by?(User.current)
@@ -265,13 +278,7 @@
helper.instance_method(:initial_page_content).bind(self).call(page)
end
- # eager load information about last updates, without loading text
- def load_pages_grouped_by_date_without_content
- @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
- :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
- :order => 'title'
- @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
- @pages_by_parent_id = @pages.group_by(&:parent_id)
+ def load_pages_for_index
+ @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/.svn/text-base/workflows_controller.rb.svn-base
--- a/app/controllers/.svn/text-base/workflows_controller.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/.svn/text-base/workflows_controller.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -32,14 +32,17 @@
if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
- (params[:issue_status] || []).each { |old, news|
- news.each { |new|
- @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
+ (params[:issue_status] || []).each { |status_id, transitions|
+ transitions.each { |new_status_id, options|
+ author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
+ assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
+ @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
}
}
if @role.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker
+ return
end
end
@@ -48,6 +51,14 @@
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.find(:all, :order => 'position')
+
+ if @tracker && @role && @statuses.any?
+ workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id})
+ @workflows = {}
+ @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
+ @workflows['author'] = workflows.select {|w| w.author}
+ @workflows['assignee'] = workflows.select {|w| w.assignee}
+ end
end
def copy
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/account_controller.rb
--- a/app/controllers/account_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/account_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -216,12 +216,24 @@
self.logged_user = user
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
- token = Token.create(:user => user, :action => 'autologin')
- cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
+ set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user })
redirect_back_or_default :controller => 'my', :action => 'page'
end
+
+ def set_autologin_cookie(user)
+ token = Token.create(:user => user, :action => 'autologin')
+ cookie_name = Redmine::Configuration['autologin_cookie_name'] || 'autologin'
+ cookie_options = {
+ :value => token.value,
+ :expires => 1.year.from_now,
+ :path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
+ :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
+ :httponly => true
+ }
+ cookies[cookie_name] = cookie_options
+ end
# Onthefly creation failed, display the registration form to fill/fix attributes
def onthefly_creation_failed(user, auth_source_options = { })
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/activities_controller.rb
--- a/app/controllers/activities_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/activities_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,11 +1,28 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class ActivitiesController < ApplicationController
menu_item :activity
before_filter :find_optional_project
- accept_key_auth :index
+ accept_rss_auth :index
def index
@days = Setting.activity_days_default.to_i
-
+
if params[:from]
begin; @date_to = params[:from].to_date + 1; rescue; end
end
@@ -14,18 +31,18 @@
@date_from = @date_to - @days
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
@author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id]))
-
- @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
+
+ @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
:with_subprojects => @with_subprojects,
:author => @author)
@activity.scope_select {|t| !params["show_#{t}"].nil?}
@activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty?
events = @activity.events(@date_from, @date_to)
-
- if events.empty? || stale?(:etag => [events.first, User.current])
+
+ if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
respond_to do |format|
- format.html {
+ format.html {
@events_by_day = events.group_by(&:event_date)
render :layout => false if request.xhr?
}
@@ -40,7 +57,7 @@
}
end
end
-
+
rescue ActiveRecord::RecordNotFound
render_404
end
@@ -55,5 +72,4 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/admin_controller.rb
--- a/app/controllers/admin_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/admin_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -17,9 +17,7 @@
class AdminController < ApplicationController
layout 'admin'
-
before_filter :require_admin
-
helper :sort
include SortHelper
@@ -30,22 +28,20 @@
def projects
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
-
unless params[:name].blank?
name = "%#{params[:name].strip.downcase}%"
c << ["LOWER(identifier) LIKE ? OR LOWER(name) LIKE ?", name, name]
end
-
@projects = Project.find :all, :order => 'lft',
:conditions => c.conditions
render :action => "projects", :layout => false if request.xhr?
end
-
+
def plugins
@plugins = Redmine::Plugin.all
end
-
+
# Loads the default configuration
# (roles, trackers, statuses, workflow, enumerations)
def default_configuration
@@ -59,7 +55,7 @@
end
redirect_to :action => 'index'
end
-
+
def test_email
raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
# Force ActionMailer to raise delivery errors so we can catch it
@@ -73,14 +69,16 @@
ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
redirect_to :controller => 'settings', :action => 'edit', :tab => 'notifications'
end
-
+
def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name
@checklist = [
- [:text_default_administrator_account_changed, User.find(:first, :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?],
+ [:text_default_administrator_account_changed,
+ User.find(:first,
+ :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?],
[:text_file_repository_writable, File.writable?(Attachment.storage_path)],
- [:text_plugin_assets_writable, File.writable?(Engines.public_directory)],
- [:text_rmagick_available, Object.const_defined?(:Magick)]
+ [:text_plugin_assets_writable, File.writable?(Engines.public_directory)],
+ [:text_rmagick_available, Object.const_defined?(:Magick)]
]
- end
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/application_controller.rb
--- a/app/controllers/application_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/application_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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.
@@ -18,34 +18,37 @@
require 'uri'
require 'cgi'
+class Unauthorized < Exception; end
+
class ApplicationController < ActionController::Base
include Redmine::I18n
layout 'base'
- exempt_from_layout 'builder'
-
+ exempt_from_layout 'builder', 'rsb'
+
# Remove broken cookie after upgrade from 0.8.x (#4292)
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360
# TODO: remove it when Rails is fixed
before_filter :delete_broken_cookies
def delete_broken_cookies
if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/
- cookies.delete '_redmine_session'
+ cookies.delete '_redmine_session'
redirect_to home_path
return false
end
end
-
+
before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password
protect_from_forgery
-
+
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
-
+ rescue_from ::Unauthorized, :with => :deny_access
+
include Redmine::Search::Controller
include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper
-
+
Redmine::Scm::Base.all.each do |scm|
require_dependency "repository/#{scm.underscore}"
end
@@ -56,7 +59,7 @@
# Find the current user
User.current = find_current_user
end
-
+
# Returns the current user or nil if no user is logged in
# and starts a session if needed
def find_current_user
@@ -68,13 +71,13 @@
user = User.try_to_autologin(cookies[:autologin])
session[:user_id] = user.id if user
user
- elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action])
+ elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session
User.find_by_rss_key(params[:key])
- elsif Setting.rest_api_enabled? && ['xml', 'json'].include?(params[:format])
- if params[:key].present? && accept_key_auth_actions.include?(params[:action])
+ elsif Setting.rest_api_enabled? && accept_api_auth?
+ if (key = api_key_from_request)
# Use API key
- User.find_by_api_key(params[:key])
+ User.find_by_api_key(key)
else
# HTTP Basic, either username/password or API key/random
authenticate_with_http_basic do |username, password|
@@ -94,14 +97,14 @@
User.current = User.anonymous
end
end
-
+
# check if login is globally required to access the application
def check_if_login_required
# no check needed if user is already logged in
return true if User.current.logged?
require_login if Setting.login_required?
- end
-
+ end
+
def set_localization
lang = nil
if User.current.logged?
@@ -117,7 +120,7 @@
lang ||= Setting.default_language
set_language_if_valid(lang)
end
-
+
def require_login
if !User.current.logged?
# Extract only the basic url parameters on non-GET requests
@@ -146,7 +149,7 @@
end
true
end
-
+
def deny_access
User.current.logged? ? render_403 : require_login
end
@@ -197,7 +200,7 @@
# Finds and sets @project based on @object.project
def find_project_from_association
render_404 unless @object.present?
-
+
@project = @object.project
rescue ActiveRecord::RecordNotFound
render_404
@@ -221,12 +224,16 @@
def find_issues
@issues = Issue.find_all_by_id(params[:id] || params[:ids])
raise ActiveRecord::RecordNotFound if @issues.empty?
+ if @issues.detect {|issue| !issue.visible?}
+ deny_access
+ return
+ end
@projects = @issues.collect(&:project).compact.uniq
@project = @projects.first if @projects.size == 1
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
# Check if project is unique before bulk operations
def check_project_uniqueness
unless @project
@@ -235,7 +242,7 @@
return false
end
end
-
+
# make sure that the user is a member of the project (or admin) if project is private
# used as a before_filter for actions that do not require any particular permission on the project
def check_project_privacy
@@ -266,7 +273,11 @@
# soundsoftware: if back_url is the home page,
# change it to My Page (#125)
if (uri.path == home_path)
- uri.path = uri.path + "/my"
+ if (uri.path =~ /\/$/)
+ uri.path = uri.path + "my"
+ else
+ uri.path = uri.path + "/my"
+ end
end
# soundsoftware: if login page is https but back_url http,
# switch back_url to https to ensure cookie validity (#83)
@@ -282,27 +293,28 @@
end
end
redirect_to default
+ false
end
-
+
def render_403(options={})
@project = nil
render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
return false
end
-
+
def render_404(options={})
render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
return false
end
-
+
# Renders an error response
def render_error(arg)
arg = {:message => arg} unless arg.is_a?(Hash)
-
+
@message = arg[:message]
@message = l(@message) if @message.is_a?(Symbol)
@status = arg[:status] || 500
-
+
respond_to do |format|
format.html {
render :template => 'common/error', :layout => use_layout, :status => @status
@@ -320,15 +332,15 @@
def use_layout
request.xhr? ? false : 'base'
end
-
+
def invalid_authenticity_token
if api_request?
logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)."
end
render_error "Invalid form authenticity token. Perhaps your session has timed out; try reloading the form and entering your details again."
end
-
- def render_feed(items, options={})
+
+ def render_feed(items, options={})
@items = items || []
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
@items = @items.slice(0, Setting.feeds_limit.to_i)
@@ -336,15 +348,42 @@
render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
end
+ # TODO: remove in Redmine 1.4
def self.accept_key_auth(*actions)
- actions = actions.flatten.map(&:to_s)
- write_inheritable_attribute('accept_key_auth_actions', actions)
+ ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
+ accept_rss_auth(*actions)
+ end
+
+ # TODO: remove in Redmine 1.4
+ def accept_key_auth_actions
+ ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth_actions is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
+ self.class.accept_rss_auth
end
- def accept_key_auth_actions
- self.class.read_inheritable_attribute('accept_key_auth_actions') || []
+ def self.accept_rss_auth(*actions)
+ if actions.any?
+ write_inheritable_attribute('accept_rss_auth_actions', actions)
+ else
+ read_inheritable_attribute('accept_rss_auth_actions') || []
+ end
end
+ def accept_rss_auth?(action=action_name)
+ self.class.accept_rss_auth.include?(action.to_sym)
+ end
+
+ def self.accept_api_auth(*actions)
+ if actions.any?
+ write_inheritable_attribute('accept_api_auth_actions', actions)
+ else
+ read_inheritable_attribute('accept_api_auth_actions') || []
+ end
+ end
+
+ def accept_api_auth?(action=action_name)
+ self.class.accept_api_auth.include?(action.to_sym)
+ end
+
# Returns the number of objects that should be displayed
# on the paginated list
def per_page_option
@@ -360,6 +399,30 @@
per_page
end
+ # Returns offset and limit used to retrieve objects
+ # for an API response based on offset, limit and page parameters
+ def api_offset_and_limit(options=params)
+ if options[:offset].present?
+ offset = options[:offset].to_i
+ if offset < 0
+ offset = 0
+ end
+ end
+ limit = options[:limit].to_i
+ if limit < 1
+ limit = 25
+ elsif limit > 100
+ limit = 100
+ end
+ if offset.nil? && options[:page].present?
+ offset = (options[:page].to_i - 1) * limit
+ offset = 0 if offset < 0
+ end
+ offset ||= 0
+
+ [offset, limit]
+ end
+
# qvalues http header parser
# code taken from webrick
def parse_qvalues(value)
@@ -380,16 +443,25 @@
rescue
nil
end
-
+
# Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
end
-
+
def api_request?
%w(xml json).include? params[:format]
end
+ # Returns the API key present in the request
+ def api_key_from_request
+ if params[:key].present?
+ params[:key]
+ elsif request.headers["X-Redmine-API-Key"].present?
+ request.headers["X-Redmine-API-Key"]
+ end
+ end
+
# Renders a warning flash if obj has unsaved attachments
def render_attachment_warning_if_needed(obj)
flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
@@ -424,5 +496,37 @@
{ attribute => error }
end.to_json
end
-
+
+ # Renders API response on validation failure
+ def render_validation_errors(object)
+ options = { :status => :unprocessable_entity, :layout => false }
+ options.merge!(case params[:format]
+ when 'xml'; { :xml => object.errors }
+ when 'json'; { :json => {'errors' => object.errors} } # ActiveResource client compliance
+ else
+ raise "Unknown format #{params[:format]} in #render_validation_errors"
+ end
+ )
+ render options
+ end
+
+ # Overrides #default_template so that the api template
+ # is used automatically if it exists
+ def default_template(action_name = self.action_name)
+ if api_request?
+ begin
+ return self.view_paths.find_template(default_template_name(action_name), 'api')
+ rescue ::ActionView::MissingTemplate
+ # the api template was not found
+ # fallback to the default behaviour
+ end
+ end
+ super
+ end
+
+ # Overrides #pick_layout so that #render with no arguments
+ # doesn't use the layout for api requests
+ def pick_layout(*args)
+ api_request? ? nil : super
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/attachments_controller.rb
--- a/app/controllers/attachments_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/attachments_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
# Redmine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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.
@@ -21,9 +21,9 @@
before_filter :file_readable, :read_authorize, :except => :destroy
before_filter :delete_authorize, :only => :destroy
before_filter :active_authorize, :only => :toggle_active
-
+
verify :method => :post, :only => :destroy
-
+
def show
if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read
@@ -35,19 +35,19 @@
download
end
end
-
+
def download
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end
-
+
# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
- :type => detect_content_type(@attachment),
+ :type => detect_content_type(@attachment),
:disposition => (@attachment.image? ? 'inline' : 'attachment')
-
+
end
-
+
def destroy
# Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment)
@@ -55,7 +55,7 @@
rescue ::ActionController::RedirectBackError
redirect_to :controller => 'projects', :action => 'show', :id => @project
end
-
+
def toggle_active
@attachment.active = !@attachment.active?
@attachment.save!
@@ -71,20 +71,20 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
# Checks that the file exists and is readable
def file_readable
@attachment.readable? ? true : render_404
end
-
+
def read_authorize
@attachment.visible? ? true : deny_access
end
-
+
def delete_authorize
@attachment.deletable? ? true : deny_access
end
-
+
def active_authorize
true
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/auto_completes_controller.rb
--- a/app/controllers/auto_completes_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/auto_completes_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -4,12 +4,14 @@
def issues
@issues = []
q = params[:q].to_s
+ query = (params[:scope] == "all" && Setting.cross_project_issue_relations?) ? Issue : @project.issues
if q.match(/^\d+$/)
- @issues << @project.issues.visible.find_by_id(q.to_i)
+ @issues << query.visible.find_by_id(q.to_i)
end
unless q.blank?
- @issues += @project.issues.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
+ @issues += query.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
end
+ @issues.compact!
render :layout => false
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/boards_controller.rb
--- a/app/controllers/boards_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/boards_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -18,7 +18,7 @@
class BoardsController < ApplicationController
default_search_scope :messages
before_filter :find_project, :find_board_if_available, :authorize
- accept_key_auth :index, :show
+ accept_rss_auth :index, :show
helper :messages
include MessagesHelper
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/calendars_controller.rb
--- a/app/controllers/calendars_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/calendars_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class CalendarsController < ApplicationController
menu_item :calendar
before_filter :find_optional_project
@@ -36,9 +53,4 @@
render :action => 'show', :layout => false if request.xhr?
end
-
- def update
- show
- end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/context_menus_controller.rb
--- a/app/controllers/context_menus_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/context_menus_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,8 +1,10 @@
class ContextMenusController < ApplicationController
helper :watchers
+ helper :issues
def issues
- @issues = Issue.find_all_by_id(params[:ids], :include => :project)
+ @issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project)
+
if (@issues.size == 1)
@issue = @issues.first
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@@ -39,5 +41,18 @@
render :layout => false
end
-
+
+ def time_entries
+ @time_entries = TimeEntry.all(
+ :conditions => {:id => params[:ids]}, :include => :project)
+ @projects = @time_entries.collect(&:project).compact.uniq
+ @project = @projects.first if @projects.size == 1
+ @activities = TimeEntryActivity.shared.active
+ @can = {:edit => User.current.allowed_to?(:log_time, @projects),
+ :update => User.current.allowed_to?(:log_time, @projects),
+ :delete => User.current.allowed_to?(:log_time, @projects)
+ }
+ @back = back_url
+ render :layout => false
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/custom_fields_controller.rb
--- a/app/controllers/custom_fields_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/custom_fields_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -38,8 +38,9 @@
flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'index', :tab => @custom_field.class.name
+ else
+ @trackers = Tracker.find(:all, :order => 'position')
end
- @trackers = Tracker.find(:all, :order => 'position')
end
def edit
@@ -48,8 +49,9 @@
flash[:notice] = l(:notice_successful_update)
call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
redirect_to :action => 'index', :tab => @custom_field.class.name
+ else
+ @trackers = Tracker.find(:all, :order => 'position')
end
- @trackers = Tracker.find(:all, :order => 'position')
end
def destroy
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/enumerations_controller.rb
--- a/app/controllers/enumerations_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/enumerations_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -75,10 +75,12 @@
# No associated objects
@enumeration.destroy
redirect_to :action => 'index'
+ return
elsif params[:reassign_to_id]
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
@enumeration.destroy(reassign_to)
redirect_to :action => 'index'
+ return
end
end
@enumerations = @enumeration.class.find(:all) - [@enumeration]
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/files_controller.rb
--- a/app/controllers/files_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/files_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -14,7 +14,7 @@
'created_on' => "#{Attachment.table_name}.created_on",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
-
+
@containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)]
@containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
render :layout => !request.xhr?
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/gantts_controller.rb
--- a/app/controllers/gantts_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/gantts_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class GanttsController < ApplicationController
menu_item :gantt
before_filter :find_optional_project
@@ -28,9 +45,4 @@
format.pdf { send_data(@gantt.to_pdf, :type => 'application/pdf', :filename => "#{basename}.pdf") }
end
end
-
- def update
- show
- end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/groups_controller.rb
--- a/app/controllers/groups_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/groups_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -132,7 +132,7 @@
def autocomplete_for_user
@group = Group.find(params[:id])
- @users = User.active.like(params[:q]).find(:all, :limit => 100) - @group.users
+ @users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100)
render :layout => false
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/issue_categories_controller.rb
--- a/app/controllers/issue_categories_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/issue_categories_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -65,10 +65,12 @@
# No issue assigned to this category
@category.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
+ return
elsif params[:todo]
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) if params[:todo] == 'reassign'
@category.destroy(reassign_to)
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
+ return
end
@categories = @project.issue_categories - [@category]
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/issue_moves_controller.rb
--- a/app/controllers/issue_moves_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/issue_moves_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -2,7 +2,7 @@
default_search_scope :issues
before_filter :find_issues, :check_project_uniqueness
before_filter :authorize
-
+
def new
prepare_for_issue_move
render :layout => false if request.xhr?
@@ -48,7 +48,7 @@
@copy = params[:copy_options] && params[:copy_options][:copy]
@allowed_projects = Issue.allowed_target_projects_on_move
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
- @target_project ||= @project
+ @target_project ||= @project
@trackers = @target_project.trackers
@available_statuses = Workflow.available_statuses(@project)
@notes = params[:notes]
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/issue_relations_controller.rb
--- a/app/controllers/issue_relations_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/issue_relations_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,4 +1,4 @@
-# redMine - project management software
+# Redmine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js do
+ @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
render :update do |page|
page.replace_html "relations", :partial => 'issues/relations'
if @relation.errors.empty?
@@ -47,7 +48,10 @@
end
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
- format.js { render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'} }
+ format.js {
+ @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
+ render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'}
+ }
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/issues_controller.rb
--- a/app/controllers/issues_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/issues_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
# Redmine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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.
@@ -18,7 +18,7 @@
class IssuesController < ApplicationController
menu_item :new_issue, :only => [:new, :create]
default_search_scope :issues
-
+
before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy]
before_filter :check_project_uniqueness, :only => [:move, :perform_move]
@@ -27,13 +27,14 @@
before_filter :find_optional_project, :only => [:index]
before_filter :check_for_default_issue_status, :only => [:new, :create]
before_filter :build_new_issue_from_params, :only => [:new, :create]
- accept_key_auth :index, :show, :create, :update, :destroy
+ accept_rss_auth :index, :show
+ accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
-
+
helper :journals
helper :projects
- include ProjectsHelper
+ include ProjectsHelper
helper :custom_fields
include CustomFieldsHelper
helper :issue_relations
@@ -44,6 +45,8 @@
include AttachmentsHelper
helper :queries
include QueriesHelper
+ helper :repositories
+ include RepositoriesHelper
helper :sort
include SortHelper
include IssuesHelper
@@ -58,34 +61,36 @@
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed }
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
-
+
def index
retrieve_query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns)
-
+
if @query.valid?
- limit = case params[:format]
+ case params[:format]
when 'csv', 'pdf'
- Setting.issues_export_limit.to_i
+ @limit = Setting.issues_export_limit.to_i
when 'atom'
- Setting.feeds_limit.to_i
+ @limit = Setting.feeds_limit.to_i
+ when 'xml', 'json'
+ @offset, @limit = api_offset_and_limit
else
- per_page_option
+ @limit = per_page_option
end
-
+
@issue_count = @query.issue_count
- @issue_pages = Paginator.new self, @issue_count, limit, params['page']
+ @issue_pages = Paginator.new self, @issue_count, @limit, params['page']
+ @offset ||= @issue_pages.current.offset
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
- :order => sort_clause,
- :offset => @issue_pages.current.offset,
- :limit => limit)
+ :order => sort_clause,
+ :offset => @offset,
+ :limit => @limit)
@issue_count_by_group = @query.issue_count_by_group
-
+
respond_to do |format|
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
- format.xml { render :layout => false }
- format.json { render :text => @issues.to_json, :layout => false }
+ format.api
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
@@ -97,21 +102,25 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
def show
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
@journals.each_with_index {|j,i| j.indice = i+1}
@journals.reverse! if User.current.wants_comments_in_reverse_order?
- @changesets = @issue.changesets.visible.all
- @changesets.reverse! if User.current.wants_comments_in_reverse_order?
+
+ if User.current.allowed_to?(:view_changesets, @project)
+ @changesets = @issue.changesets.visible.all
+ @changesets.reverse! if User.current.wants_comments_in_reverse_order?
+ end
+
+ @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.all
- @time_entry = TimeEntry.new
+ @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
respond_to do |format|
format.html { render :template => 'issues/show.rhtml' }
- format.xml { render :layout => false }
- format.json { render :text => @issue.to_json, :layout => false }
+ format.api
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
end
@@ -147,19 +156,17 @@
redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
{ :action => 'show', :id => @issue })
}
- format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
- format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
+ format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
end
return
else
respond_to do |format|
format.html { render :action => 'new' }
- format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
- format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
+ format.api { render_validation_errors(@issue) }
end
end
end
-
+
def edit
update_issue_from_params
@@ -180,8 +187,7 @@
respond_to do |format|
format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
- format.xml { head :ok }
- format.json { head :ok }
+ format.api { head :ok }
end
else
render_attachment_warning_if_needed(@issue)
@@ -190,8 +196,7 @@
respond_to do |format|
format.html { render :action => 'edit' }
- format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
- format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
+ format.api { render_validation_errors(@issue) }
end
end
end
@@ -223,7 +228,7 @@
set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
end
-
+
def destroy
@hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
if @hours > 0
@@ -241,35 +246,44 @@
TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
end
else
- unless params[:format] == 'xml' || params[:format] == 'json'
- # display the destroy form if it's a user request
- return
- end
+ # display the destroy form if it's a user request
+ return unless api_request?
end
end
- @issues.each(&:destroy)
+ @issues.each do |issue|
+ begin
+ issue.reload.destroy
+ rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
+ # nothing to do, issue was already deleted (eg. by a parent)
+ end
+ end
respond_to do |format|
format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
- format.xml { head :ok }
- format.json { head :ok }
+ format.api { head :ok }
end
end
private
def find_issue
+ # Issue.visible.find(...) can not be used to redirect user to the login form
+ # if the issue actually exists but requires authentication
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
+ unless @issue.visible?
+ deny_access
+ return
+ end
@project = @issue.project
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
def find_project
project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
@project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
# Used by #edit and #update to set some common instance variables
# from the params
# TODO: Refactor, not everything in here is needed by #edit
@@ -277,9 +291,9 @@
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.all
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
- @time_entry = TimeEntry.new
+ @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry]
-
+
@notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil)
@issue.init_journal(User.current, @notes)
@issue.safe_attributes = params[:issue]
@@ -288,7 +302,7 @@
# is in this issues watcher's list
# if not, adds it.
- if params[:issue][:assigned_to_id] && !params[:issue][:assigned_to_id].empty?:
+ if params[:issue] && params[:issue][:assigned_to_id] && !params[:issue][:assigned_to_id].empty?:
unless @issue.watched_by?(User.find(params[:issue][:assigned_to_id])):
@issue.add_watcher(User.find(params[:issue][:assigned_to_id]))
end
@@ -307,8 +321,9 @@
else
@issue = @project.issues.visible.find(params[:id])
end
-
+
@issue.project = @project
+ @issue.author = User.current
# Tracker must be set before custom field values
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
if @issue.tracker.nil?
@@ -322,7 +337,6 @@
@issue.watcher_user_ids = params[:issue]['watcher_user_ids']
end
end
- @issue.author = User.current
@priorities = IssuePriority.all
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/journals_controller.rb
--- a/app/controllers/journals_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/journals_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -16,12 +16,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class JournalsController < ApplicationController
- before_filter :find_journal, :only => [:edit]
+ before_filter :find_journal, :only => [:edit, :diff]
before_filter :find_issue, :only => [:new]
before_filter :find_optional_project, :only => [:index]
- accept_key_auth :index
-
+ before_filter :authorize, :only => [:new, :edit, :diff]
+ accept_rss_auth :index
+ menu_item :issues
+
helper :issues
+ helper :custom_fields
helper :queries
include QueriesHelper
helper :sort
@@ -42,6 +45,17 @@
render_404
end
+ def diff
+ @issue = @journal.issue
+ if params[:detail_id].present?
+ @detail = @journal.details.find_by_id(params[:detail_id])
+ else
+ @detail = @journal.details.detect {|d| d.prop_key == 'description'}
+ end
+ (render_404; return false) unless @issue && @detail
+ @diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
+ end
+
def new
journal = Journal.find(params[:journal_id]) if params[:journal_id]
if journal
@@ -66,6 +80,7 @@
end
def edit
+ (render_403; return false) unless @journal.editable_by?(User.current)
if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank?
@@ -74,13 +89,21 @@
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id }
format.js { render :action => 'update' }
end
+ else
+ respond_to do |format|
+ format.html {
+ # TODO: implement non-JS journal update
+ render :nothing => true
+ }
+ format.js
+ end
end
end
-private
+ private
+
def find_journal
@journal = Journal.find(params[:id])
- (render_403; return false) unless @journal.editable_by?(User.current)
@project = @journal.journalized.project
rescue ActiveRecord::RecordNotFound
render_404
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/mail_handler_controller.rb
--- a/app/controllers/mail_handler_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/mail_handler_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,27 +1,27 @@
-# redMine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MailHandlerController < ActionController::Base
before_filter :check_credential
-
+
verify :method => :post,
:only => :index,
:render => { :nothing => true, :status => 405 }
-
+
# Submits an incoming email to MailHandler
def index
options = params.dup
@@ -32,9 +32,9 @@
render :nothing => true, :status => :unprocessable_entity
end
end
-
+
private
-
+
def check_credential
User.current = nil
unless Setting.mail_handler_api_enabled? && params[:key].to_s == Setting.mail_handler_api_key
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/members_controller.rb
--- a/app/controllers/members_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/members_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -17,11 +17,22 @@
class MembersController < ApplicationController
model_object Member
- before_filter :find_model_object, :except => [:new, :autocomplete_for_member]
- before_filter :find_project_from_association, :except => [:new, :autocomplete_for_member]
+ menu_item :members
+ before_filter :find_model_object, :except => [:index, :new, :autocomplete_for_member]
+ before_filter :find_project_from_association, :except => [:new, :index, :autocomplete_for_member]
before_filter :find_project, :only => [:new, :autocomplete_for_member]
+ before_filter :find_project_by_project_id, :only => [:index]
before_filter :authorize
+ def index
+ logger.debug('in index')
+ respond_to do |format|
+ format.html {
+ render :layout => false if request.xhr?
+ }
+ end
+ end
+
def new
members = []
if params[:member] && request.post?
@@ -50,11 +61,11 @@
respond_to do |format|
if members.present? && members.all? {|m| m.valid? }
- format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
+ format.html { redirect_to :action => 'index', :project_id => @project }
format.js {
render(:update) {|page|
- page.replace_html "tab-content-members", :partial => 'projects/settings/members'
+ page.replace_html "memberlist", :partial => 'editlist'
page << 'hideOnLoad()'
members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
}
@@ -78,10 +89,10 @@
def edit
if request.post? and @member.update_attributes(params[:member])
respond_to do |format|
- format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
+ format.html { redirect_to :action => 'index', :project_id => @project }
format.js {
render(:update) {|page|
- page.replace_html "tab-content-members", :partial => 'projects/settings/members'
+ page.replace_html "memberlist", :partial => 'editlist'
page << 'hideOnLoad()'
page.visual_effect(:highlight, "member-#{@member.id}")
}
@@ -95,9 +106,9 @@
@member.destroy
end
respond_to do |format|
- format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
+ format.html { redirect_to :action => 'index', :project_id => @project }
format.js { render(:update) {|page|
- page.replace_html "tab-content-members", :partial => 'projects/settings/members'
+ page.replace_html "memberlist", :partial => 'editlist'
page << 'hideOnLoad()'
}
}
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/my_controller.rb
--- a/app/controllers/my_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/my_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -19,6 +19,7 @@
before_filter :require_login
helper :issues
+ helper :users
helper :custom_fields
BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
@@ -33,7 +34,7 @@
}.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
DEFAULT_LAYOUT = { 'left' => ['tipoftheday', 'activitymyprojects'],
- 'right' => ['issueswatched','calendar']
+ 'right' => ['issueswatched']
}.freeze
verify :xhr => true,
@@ -64,8 +65,7 @@
end
if request.post?
- @user.attributes = params[:user]
- @user.mail_notification = params[:notification_option] || 'only_my_events'
+ @user.safe_attributes = params[:user]
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
@@ -90,15 +90,13 @@
if @user.save
@user.pref.save
- @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
+ @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
set_language_if_valid @user.language
flash[:notice] = l(:notice_account_updated)
redirect_to :action => 'account'
return
end
end
- @notification_options = @user.valid_notification_options
- @notification_option = @user.mail_notification #? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected')
end
# Manage user's password
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/news_controller.rb
--- a/app/controllers/news_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/news_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -23,18 +23,32 @@
before_filter :find_project, :only => [:new, :create]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => :index
- accept_key_auth :index
+ accept_rss_auth :index
+ accept_api_auth :index
+
+ helper :watchers
def index
- @news_pages, @newss = paginate :news,
- :per_page => 10,
- :conditions => Project.allowed_to_condition(User.current, :view_news, :project => @project),
- :include => [:author, :project],
- :order => "#{News.table_name}.created_on DESC"
+ case params[:format]
+ when 'xml', 'json'
+ @offset, @limit = api_offset_and_limit
+ else
+ @limit = 10
+ end
+
+ scope = @project ? @project.news.visible : News.visible
+
+ @news_count = scope.count
+ @news_pages = Paginator.new self, @news_count, @limit, params['page']
+ @offset ||= @news_pages.current.offset
+ @newss = scope.all(:include => [:author, :project],
+ :order => "#{News.table_name}.created_on DESC",
+ :offset => @offset,
+ :limit => @limit)
+
respond_to do |format|
format.html { render :layout => false if request.xhr? }
- format.xml { render :xml => @newss.to_xml }
- format.json { render :json => @newss.to_json }
+ format.api
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/previews_controller.rb
--- a/app/controllers/previews_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/previews_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
class PreviewsController < ApplicationController
before_filter :find_project
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/projects_controller.rb
--- a/app/controllers/projects_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/projects_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -24,7 +24,8 @@
before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
before_filter :authorize_global, :only => [:new, :create]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
- accept_key_auth :index
+ accept_rss_auth :index
+ accept_api_auth :index, :show, :create, :update, :destroy
after_filter :only => [:create, :edit, :update, :archive, :unarchive, :destroy] do |controller|
if controller.request.post?
@@ -32,9 +33,6 @@
end
end
- # TODO: convert to PUT only
- verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
-
helper :sort
include SortHelper
helper :custom_fields
@@ -65,8 +63,10 @@
end
render :template => 'projects/index.rhtml', :layout => !request.xhr?
}
- format.xml {
- @projects = Project.visible.find(:all, :order => 'lft')
+ format.api {
+ @offset, @limit = api_offset_and_limit
+ @project_count = Project.visible.count
+ @projects = Project.visible.all(:offset => @offset, :limit => @limit, :order => 'lft')
}
format.atom {
projects = Project.visible.find(:all, :order => 'created_on DESC',
@@ -80,19 +80,15 @@
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all
@project = Project.new(params[:project])
-
- @project.identifier = Project.next_identifier if Setting.sequential_project_identifiers?
- @project.trackers = Tracker.all
- @project.is_public = Setting.default_projects_public?
- @project.enabled_module_names = Setting.default_projects_modules
end
+ verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all
- @project = Project.new(params[:project])
+ @project = Project.new
+ @project.safe_attributes = params[:project]
- @project.enabled_module_names = params[:enabled_modules]
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
@@ -106,12 +102,12 @@
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'projects', :action => 'settings', :id => @project
}
- format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
+ format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
end
else
respond_to do |format|
format.html { render :action => 'new' }
- format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
+ format.api { render_validation_errors(@project) }
end
end
@@ -133,18 +129,18 @@
end
else
Mailer.with_deliveries(params[:notifications] == '1') do
- @project = Project.new(params[:project])
- @project.enabled_module_names = params[:enabled_modules]
+ @project = Project.new
+ @project.safe_attributes = params[:project]
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
flash[:notice] = l(:notice_successful_create)
- redirect_to :controller => 'projects', :action => 'settings'
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
elsif !@project.new_record?
# Project was created
# But some objects were not copied due to validation failures
# (eg. issues from disabled trackers)
# TODO: inform about that
- redirect_to :controller => 'projects', :action => 'settings'
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project
end
end
end
@@ -160,7 +156,7 @@
end
@users_by_role = @project.users_by_role
- @subprojects = @project.children.visible
+ @subprojects = @project.children.visible.all
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = @project.rolled_up_trackers
@@ -173,16 +169,15 @@
:include => [:project, :status, :tracker],
:conditions => cond)
- TimeEntry.visible_by(User.current) do
- @total_hours = TimeEntry.sum(:hours,
- :include => :project,
- :conditions => cond).to_f
+ if User.current.allowed_to?(:view_time_entries, @project)
+ @total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f
end
+
@key = User.current.rss_key
respond_to do |format|
format.html
- format.xml
+ format.api
end
end
@@ -198,8 +193,10 @@
def edit
end
+ # TODO: convert to PUT only
+ verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update
- @project.attributes = params[:project]
+ @project.safe_attributes = params[:project]
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
respond_to do |format|
@@ -207,7 +204,7 @@
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project
}
- format.xml { head :ok }
+ format.api { head :ok }
end
else
respond_to do |format|
@@ -215,11 +212,13 @@
settings
render :action => 'settings'
}
- format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
+ format.api { render_validation_errors(@project) }
end
end
end
+ verify :method => :post, :only => :modules, :render => {:nothing => true, :status => :method_not_allowed }
+
def overview
@project.has_welcome_page = params[:has_welcome_page]
if @project.save
@@ -229,7 +228,7 @@
end
def modules
- @project.enabled_module_names = params[:enabled_modules]
+ @project.enabled_module_names = params[:enabled_module_names]
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project, :tab => 'modules'
end
@@ -254,11 +253,11 @@
if request.get?
# display confirmation view
else
- if params[:format] == 'xml' || params[:confirm]
+ if api_request? || params[:confirm]
@project_to_destroy.destroy
respond_to do |format|
format.html { redirect_to :controller => 'admin', :action => 'projects' }
- format.xml { head :ok }
+ format.api { head :ok }
end
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/queries_controller.rb
--- a/app/controllers/queries_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/queries_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -25,11 +25,12 @@
@query.project = params[:query_is_for_all] ? nil : @project
@query.user = User.current
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
+
+ @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
+ @query.group_by ||= params[:group_by]
+ @query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
- @query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields]
- @query.group_by ||= params[:group_by]
-
if request.post? && params[:confirm] && @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query
@@ -41,10 +42,12 @@
def edit
if request.post?
@query.filters = {}
- @query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields]
+ @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.attributes = params[:query]
@query.project = nil if params[:query_is_for_all]
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
+ @query.group_by ||= params[:group_by]
+ @query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
if @query.save
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/repositories_controller.rb
--- a/app/controllers/repositories_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/repositories_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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.
@@ -26,14 +26,14 @@
menu_item :repository
menu_item :settings, :only => :edit
default_search_scope :changesets
-
+
before_filter :find_repository, :except => :edit
before_filter :find_project, :only => :edit
before_filter :authorize
- accept_key_auth :revisions
-
+ accept_rss_auth :revisions
+
rescue_from Redmine::Scm::Adapters::CommandFailed, :with => :show_error_command_failed
-
+
def edit
@repository = @project.repository
@@ -45,19 +45,31 @@
@repository.project = @project if @repository
end
if request.post? && @repository
- @repository.attributes = params[:repository]
+ p1 = params[:repository]
+ p = {}
+ p_extra = {}
+ p1.each do |k, v|
+ if k =~ /^extra_/
+ p_extra[k] = v
+ else
+ p[k] = v
+ end
+ end
+ @repository.attributes = p
+ @repository.merge_extra_info(p_extra)
@repository.save
end
render(:update) do |page|
- page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'
+ page.replace_html "tab-content-repository",
+ :partial => 'projects/settings/repository'
if @repository && !@project.repository
- @project.reload #needed to reload association
+ @project.reload # needed to reload association
page.replace_html "main-menu", render_main_menu(@project)
end
end
end
-
+
def committers
@committers = @repository.committers
@users = @project.users
@@ -72,16 +84,20 @@
redirect_to :action => 'committers', :id => @project
end
end
-
+
def destroy
@repository.destroy
- redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
+ redirect_to :controller => 'projects',
+ :action => 'settings',
+ :id => @project,
+ :tab => 'repository'
end
-
- def show
+
+ def show
@repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
@entries = @repository.entries(@path, @rev)
+ @changeset = @repository.find_changeset_by_name(@rev)
if request.xhr?
@entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
else
@@ -93,30 +109,31 @@
end
alias_method :browse, :show
-
+
def changes
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
@changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i)
@properties = @repository.properties(@path, @rev)
+ @changeset = @repository.find_changeset_by_name(@rev)
end
-
+
def revisions
@changeset_count = @repository.changesets.count
@changeset_pages = Paginator.new self, @changeset_count,
- per_page_option,
- params['page']
+ per_page_option,
+ params['page']
@changesets = @repository.changesets.find(:all,
- :limit => @changeset_pages.items_per_page,
- :offset => @changeset_pages.current.offset,
- :include => [:user, :repository])
+ :limit => @changeset_pages.items_per_page,
+ :offset => @changeset_pages.current.offset,
+ :include => [:user, :repository])
respond_to do |format|
format.html { render :layout => false if request.xhr? }
format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") }
end
end
-
+
def entry
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
@@ -126,24 +143,46 @@
@content = @repository.cat(@path, @rev)
(show_error_not_found; return) unless @content
- if 'raw' == params[:format] || @content.is_binary_data? || (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte)
+ if 'raw' == params[:format] ||
+ (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
+ ! is_entry_text_data?(@content, @path)
# Force the download
- send_data @content, :filename => @path.split('/').last
+ send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
+ send_type = Redmine::MimeType.of(@path)
+ send_opt[:type] = send_type.to_s if send_type
+ send_data @content, send_opt
else
# Prevent empty lines when displaying a file with Windows style eol
+ # TODO: UTF-16
+ # Is this needs? AttachmentsController reads file simply.
@content.gsub!("\r\n", "\n")
- end
+ @changeset = @repository.find_changeset_by_name(@rev)
+ end
end
-
+
+ def is_entry_text_data?(ent, path)
+ # UTF-16 contains "\x00".
+ # It is very strict that file contains less than 30% of ascii symbols
+ # in non Western Europe.
+ return true if Redmine::MimeType.is_type?('text', path)
+ # Ruby 1.8.6 has a bug of integer divisions.
+ # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
+ return false if ent.is_binary_data?
+ true
+ end
+ private :is_entry_text_data?
+
def annotate
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
-
+
@annotate = @repository.scm.annotate(@path, @rev)
(render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
+ @changeset = @repository.find_changeset_by_name(@rev)
end
-
+
def revision
+ raise ChangesetNotFound if @rev.blank?
@changeset = @repository.find_changeset_by_name(@rev)
raise ChangesetNotFound unless @changeset
@@ -154,7 +193,7 @@
rescue ChangesetNotFound
show_error_not_found
end
-
+
def diff
if params[:format] == 'diff'
@diff = @repository.diff(@path, @rev, @rev_to)
@@ -167,26 +206,30 @@
else
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
-
+
# Save diff type as user preference
if User.current.logged? && @diff_type != User.current.pref[:diff_type]
User.current.pref[:diff_type] = @diff_type
User.current.preference.save
end
-
- @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
+ @cache_key = "repositories/diff/#{@repository.id}/" +
+ Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
unless read_fragment(@cache_key)
@diff = @repository.diff(@path, @rev, @rev_to)
show_error_not_found unless @diff
end
+
+ @changeset = @repository.find_changeset_by_name(@rev)
+ @changeset_to = @rev_to ? @repository.find_changeset_by_name(@rev_to) : nil
+ @diff_format_revisions = @repository.diff_format_revisions(@changeset, @changeset_to)
end
end
-
- def stats
+
+ def stats
end
-
+
def graph
- data = nil
+ data = nil
case params[:graph]
when "commits_per_month"
data = graph_commits_per_month(@repository)
@@ -200,8 +243,11 @@
render_404
end
end
-
-private
+
+ private
+
+ REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
+
def find_repository
@project = Project.find(params[:id])
@repository = @project.repository
@@ -210,6 +256,12 @@
@path ||= ''
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
@rev_to = params[:rev_to]
+
+ unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
+ if @repository.branches.blank?
+ raise InvalidRevisionParam
+ end
+ end
rescue ActiveRecord::RecordNotFound
render_404
rescue InvalidRevisionParam
@@ -217,29 +269,33 @@
end
def show_error_not_found
- render_error l(:error_scm_not_found)
+ render_error :message => l(:error_scm_not_found), :status => 404
end
-
+
# Handler for Redmine::Scm::Adapters::CommandFailed exception
def show_error_command_failed(exception)
render_error l(:error_scm_command_failed, exception.message)
end
-
+
def graph_commits_per_month(repository)
@date_to = Date.today
@date_from = @date_to << 11
@date_from = Date.civil(@date_from.year, @date_from.month, 1)
- commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
+ commits_by_day = repository.changesets.count(
+ :all, :group => :commit_date,
+ :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
commits_by_month = [0] * 12
commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
- changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
+ changes_by_day = repository.changes.count(
+ :all, :group => :commit_date,
+ :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
changes_by_month = [0] * 12
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
-
+
fields = []
12.times {|m| fields << month_name(((Date.today.month - 1 - m) % 12) + 1)}
-
+
graph = SVG::Graph::Bar.new(
:height => 300,
:width => 800,
@@ -251,7 +307,7 @@
:graph_title => l(:label_commits_per_month),
:show_graph_title => true
)
-
+
graph.add_data(
:data => commits_by_month[0..11].reverse,
:title => l(:label_revision_plural)
@@ -261,7 +317,7 @@
:data => changes_by_month[0..11].reverse,
:title => l(:label_change_plural)
)
-
+
graph.burn
end
@@ -271,18 +327,18 @@
changes_by_author = repository.changes.count(:all, :group => :committer)
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
-
+
fields = commits_by_author.collect {|r| r.first}
commits_data = commits_by_author.collect {|r| r.last}
changes_data = commits_by_author.collect {|r| h[r.first] || 0}
-
+
fields = fields + [""]*(10 - fields.length) if fields.length<10
commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
-
+
# Remove email adress in usernames
fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') }
-
+
graph = SVG::Graph::BarHorizontal.new(
:height => 400,
:width => 800,
@@ -294,22 +350,18 @@
:graph_title => l(:label_commits_per_author),
:show_graph_title => true
)
-
graph.add_data(
:data => commits_data,
:title => l(:label_revision_plural)
)
-
graph.add_data(
:data => changes_data,
:title => l(:label_change_plural)
)
-
graph.burn
end
+end
-end
-
class Date
def months_ago(date = Date.today)
(date.year - self.year)*12 + (date.month - self.month)
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/roles_controller.rb
--- a/app/controllers/roles_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/roles_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -38,9 +38,10 @@
end
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'index'
+ else
+ @permissions = @role.setable_permissions
+ @roles = Role.find :all, :order => 'builtin, position'
end
- @permissions = @role.setable_permissions
- @roles = Role.find :all, :order => 'builtin, position'
end
def edit
@@ -48,8 +49,9 @@
if request.post? and @role.update_attributes(params[:role])
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index'
+ else
+ @permissions = @role.setable_permissions
end
- @permissions = @role.setable_permissions
end
def destroy
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/search_controller.rb
--- a/app/controllers/search_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/search_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -24,8 +24,8 @@
def index
@question = params[:q] || ""
@question.strip!
- @all_words = params[:all_words] || (params[:submit] ? false : true)
- @titles_only = !params[:titles_only].nil?
+ @all_words = params[:all_words] ? params[:all_words].present? : true
+ @titles_only = params[:titles_only] ? params[:titles_only].present? : false
projects_to_search =
case params[:scope]
@@ -69,6 +69,7 @@
# no more than 5 tokens to search for
@tokens.slice! 5..-1 if @tokens.size > 5
+ @project_matches = []
@results = []
@results_by_type = Hash.new {|h,k| h[k] = 0}
@@ -82,6 +83,12 @@
:before => params[:previous].nil?)
@results += r
@results_by_type[s] += c
+ if s == 'projects'
+ r, c = s.singularize.camelcase.constantize.search(@tokens, nil,
+ :all_words => @all_words,
+ :titles_only => 1)
+ @project_matches += r
+ end
end
@results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime}
if params[:previous].nil?
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/settings_controller.rb
--- a/app/controllers/settings_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/settings_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -17,7 +17,7 @@
class SettingsController < ApplicationController
layout 'admin'
-
+
before_filter :require_admin
def index
@@ -36,14 +36,16 @@
end
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :tab => params[:tab]
- return
+ else
+ @options = {}
+ @options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
+ @deliveries = ActionMailer::Base.perform_deliveries
+
+ @guessed_host_and_path = request.host_with_port.dup
+ @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
+
+ Redmine::Themes.rescan
end
- @options = {}
- @options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
- @deliveries = ActionMailer::Base.perform_deliveries
-
- @guessed_host_and_path = request.host_with_port.dup
- @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
end
def plugin
@@ -52,9 +54,10 @@
Setting["plugin_#{@plugin.id}"] = params[:settings]
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'plugin', :id => @plugin.id
+ else
+ @partial = @plugin.settings[:partial]
+ @settings = Setting["plugin_#{@plugin.id}"]
end
- @partial = @plugin.settings[:partial]
- @settings = Setting["plugin_#{@plugin.id}"]
rescue Redmine::PluginNotFound
render_404
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/timelog_controller.rb
--- a/app/controllers/timelog_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/timelog_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -18,10 +18,13 @@
class TimelogController < ApplicationController
menu_item :issues
before_filter :find_project, :only => [:new, :create]
- before_filter :find_time_entry, :only => [:edit, :update, :destroy]
+ before_filter :find_time_entry, :only => [:show, :edit, :update]
+ before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => [:index]
-
+ accept_rss_auth :index
+ accept_api_auth :index, :show, :create, :update, :destroy
+
helper :sort
include SortHelper
helper :issues
@@ -39,50 +42,64 @@
'hours' => 'hours'
cond = ARCondition.new
- if @project.nil?
- cond << Project.allowed_to_condition(User.current, :view_time_entries)
- elsif @issue.nil?
+ if @issue
+ cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
+ elsif @project
cond << @project.project_condition(Setting.display_subprojects_issues?)
- else
- cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
end
retrieve_date_range
cond << ['spent_on BETWEEN ? AND ?', @from, @to]
- TimeEntry.visible_by(User.current) do
- respond_to do |format|
- format.html {
- # Paginate results
- @entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions)
- @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => sort_clause,
- :limit => @entry_pages.items_per_page,
- :offset => @entry_pages.current.offset)
- @total_hours = TimeEntry.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
+ respond_to do |format|
+ format.html {
+ # Paginate results
+ @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
+ @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => sort_clause,
+ :limit => @entry_pages.items_per_page,
+ :offset => @entry_pages.current.offset)
+ @total_hours = TimeEntry.visible.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
- render :layout => !request.xhr?
- }
- format.atom {
- entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => "#{TimeEntry.table_name}.created_on DESC",
- :limit => Setting.feeds_limit.to_i)
- render_feed(entries, :title => l(:label_spent_time))
- }
- format.csv {
- # Export all entries
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
- :conditions => cond.conditions,
- :order => sort_clause)
- send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
- }
- end
+ render :layout => !request.xhr?
+ }
+ format.api {
+ @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
+ @offset, @limit = api_offset_and_limit
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => sort_clause,
+ :limit => @limit,
+ :offset => @offset)
+ }
+ format.atom {
+ entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => "#{TimeEntry.table_name}.created_on DESC",
+ :limit => Setting.feeds_limit.to_i)
+ render_feed(entries, :title => l(:label_spent_time))
+ }
+ format.csv {
+ # Export all entries
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
+ :conditions => cond.conditions,
+ :order => sort_clause)
+ send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
+ }
+ end
+ end
+
+ def show
+ respond_to do |format|
+ # TODO: Implement html response
+ format.html { render :nothing => true, :status => 406 }
+ format.api
end
end
@@ -102,10 +119,18 @@
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
- flash[:notice] = l(:notice_successful_update)
- redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_update)
+ redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ }
+ format.api { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
+ end
else
- render :action => 'edit'
+ respond_to do |format|
+ format.html { render :action => 'edit' }
+ format.api { render_validation_errors(@time_entry) }
+ end
end
end
@@ -122,23 +147,70 @@
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
- flash[:notice] = l(:notice_successful_update)
- redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_update)
+ redirect_back_or_default :action => 'index', :project_id => @time_entry.project
+ }
+ format.api { head :ok }
+ end
else
- render :action => 'edit'
+ respond_to do |format|
+ format.html { render :action => 'edit' }
+ format.api { render_validation_errors(@time_entry) }
+ end
end
end
+ def bulk_edit
+ @available_activities = TimeEntryActivity.shared.active
+ @custom_fields = TimeEntry.first.available_custom_fields
+ end
+
+ def bulk_update
+ attributes = parse_params_for_bulk_time_entry_attributes(params)
+
+ unsaved_time_entry_ids = []
+ @time_entries.each do |time_entry|
+ time_entry.reload
+ time_entry.attributes = attributes
+ call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
+ unless time_entry.save
+ # Keep unsaved time_entry ids to display them in flash error
+ unsaved_time_entry_ids << time_entry.id
+ end
+ end
+ set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
+ redirect_back_or_default({:controller => 'timelog', :action => 'index', :project_id => @projects.first})
+ end
+
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy
- if @time_entry.destroy && @time_entry.destroyed?
- flash[:notice] = l(:notice_successful_delete)
- else
- flash[:error] = l(:notice_unable_delete_time_entry)
+ @time_entries.each do |t|
+ begin
+ unless t.destroy && t.destroyed?
+ respond_to do |format|
+ format.html {
+ flash[:error] = l(:notice_unable_delete_time_entry)
+ redirect_to :back
+ }
+ format.api { render_validation_errors(t) }
+ end
+ return
+ end
+ rescue ::ActionController::RedirectBackError
+ redirect_to :action => 'index', :project_id => @projects.first
+ return
+ end
end
- redirect_to :back
- rescue ::ActionController::RedirectBackError
- redirect_to :action => 'index', :project_id => @time_entry.project
+
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_delete)
+ redirect_back_or_default(:action => 'index', :project_id => @projects.first)
+ }
+ format.api { head :ok }
+ end
end
private
@@ -153,12 +225,32 @@
render_404
end
+ def find_time_entries
+ @time_entries = TimeEntry.find_all_by_id(params[:id] || params[:ids])
+ raise ActiveRecord::RecordNotFound if @time_entries.empty?
+ @projects = @time_entries.collect(&:project).compact.uniq
+ @project = @projects.first if @projects.size == 1
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+
+ def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids)
+ if unsaved_time_entry_ids.empty?
+ flash[:notice] = l(:notice_successful_update) unless time_entries.empty?
+ else
+ flash[:error] = l(:notice_failed_to_save_time_entries,
+ :count => unsaved_time_entry_ids.size,
+ :total => time_entries.size,
+ :ids => '#' + unsaved_time_entry_ids.join(', #'))
+ end
+ end
+
def find_project
- if params[:issue_id]
- @issue = Issue.find(params[:issue_id])
+ if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
+ @issue = Issue.find(issue_id)
@project = @issue.project
- elsif params[:project_id]
- @project = Project.find(params[:project_id])
+ elsif (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
+ @project = Project.find(project_id)
else
render_404
return false
@@ -223,4 +315,10 @@
@to ||= (TimeEntry.latest_date_for_project(@project) || Date.today)
end
+ def parse_params_for_bulk_time_entry_attributes(params)
+ attributes = (params[:time_entry] || {}).reject {|k,v| v.blank?}
+ attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
+ attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
+ attributes
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/users_controller.rb
--- a/app/controllers/users_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/users_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -19,6 +19,8 @@
layout 'admin'
before_filter :require_admin, :except => :show
+ before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
+ accept_api_auth :index, :show, :create, :update, :destroy
helper :sort
include SortHelper
@@ -29,6 +31,16 @@
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
+ case params[:format]
+ when 'xml', 'json'
+ @offset, @limit = api_offset_and_limit
+ else
+ @limit = per_page_option
+ end
+
+ scope = User
+ scope = scope.in_group(params[:group_id].to_i) if params[:group_id].present?
+
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
@@ -37,20 +49,25 @@
c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name]
end
- @user_count = User.count(:conditions => c.conditions)
- @user_pages = Paginator.new self, @user_count,
- per_page_option,
- params['page']
- @users = User.find :all,:order => sort_clause,
+ @user_count = scope.count(:conditions => c.conditions)
+ @user_pages = Paginator.new self, @user_count, @limit, params['page']
+ @offset ||= @user_pages.current.offset
+ @users = scope.find :all,
+ :order => sort_clause,
:conditions => c.conditions,
- :limit => @user_pages.items_per_page,
- :offset => @user_pages.current.offset
+ :limit => @limit,
+ :offset => @offset
- render :layout => !request.xhr?
+ respond_to do |format|
+ format.html {
+ @groups = Group.all.sort
+ render :layout => !request.xhr?
+ }
+ format.api
+ end
end
def show
- @user = User.find(params[:id])
if @user.ssamr_user_detail != nil
@description = @user.ssamr_user_detail.description
@@ -66,7 +83,7 @@
end
# show projects based on current user visibility
- @memberships = @user.memberships.all(:conditions => Project.visible_by(User.current))
+ @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current))
events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
@events_by_day = events.group_by(&:event_date)
@@ -77,17 +94,15 @@
return
end
end
- render :layout => 'base'
-
- rescue ActiveRecord::RecordNotFound
- render_404
+
+ respond_to do |format|
+ format.html { render :layout => 'base' }
+ format.api
+ end
end
def new
- @notification_options = User::MAIL_NOTIFICATION_OPTIONS
- @notification_option = Setting.default_notification_option
-
- @user = User.new(:language => Setting.default_language)
+ @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
@auth_sources = AuthSource.find(:all)
@ssamr_user_details = SsamrUserDetail.new
@@ -95,16 +110,14 @@
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
- @notification_options = User::MAIL_NOTIFICATION_OPTIONS
- @notification_option = Setting.default_notification_option
-
+ @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
+ @user.safe_attributes = params[:user]
@user = User.new(params[:user])
@user.admin = params[:user][:admin] || false
@user.login = params[:user][:login]
- @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
+ @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
# TODO: Similar to My#account
- @user.mail_notification = params[:notification_option] || 'only_my_events'
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
@@ -118,25 +131,32 @@
@ssamr_user_details.save!
- @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
- Mailer.deliver_account_information(@user, params[:password]) if params[:send_information]
- flash[:notice] = l(:notice_successful_create)
- redirect_to(params[:continue] ? {:controller => 'users', :action => 'new'} :
- {:controller => 'users', :action => 'edit', :id => @user})
- return
+ Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information]
+
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to(params[:continue] ?
+ {:controller => 'users', :action => 'new'} :
+ {:controller => 'users', :action => 'edit', :id => @user}
+ )
+ }
+ format.api { render :action => 'show', :status => :created, :location => user_url(@user) }
+ end
else
@auth_sources = AuthSource.find(:all)
- @notification_option = @user.mail_notification
+ # Clear password input
+ @user.password = @user.password_confirmation = nil
- render :action => 'new'
+ respond_to do |format|
+ format.html { render :action => 'new' }
+ format.api { render_validation_errors(@user) }
+ end
end
end
def edit
- @user = User.find(params[:id])
- @notification_options = @user.valid_notification_options
- @notification_option = @user.mail_notification
@ssamr_user_details = @user.ssamr_user_detail
@@ -152,22 +172,15 @@
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update
- @user = User.find(params[:id])
-
- @notification_options = @user.valid_notification_options
- @notification_option = @user.mail_notification
-
@user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login]
- if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
- @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
+ if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
+ @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation]
end
- @user.group_ids = params[:user][:group_ids] if params[:user][:group_ids]
- @user.attributes = params[:user]
+ @user.safe_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])
# TODO: Similar to My#account
- @user.mail_notification = params[:notification_option] || 'only_my_events'
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
@@ -193,27 +206,46 @@
if @user.save
@user.pref.save
- @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
+ @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
if was_activated
Mailer.deliver_account_activated(@user)
- elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil?
- Mailer.deliver_account_information(@user, params[:password])
+ elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
+ Mailer.deliver_account_information(@user, params[:user][:password])
end
- flash[:notice] = l(:notice_successful_update)
- redirect_to :back
+
+ respond_to do |format|
+ format.html {
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :back
+ }
+ format.api { head :ok }
+ end
else
@auth_sources = AuthSource.find(:all)
@membership ||= Member.new
+ # Clear password input
+ @user.password = @user.password_confirmation = nil
- render :action => :edit
+ respond_to do |format|
+ format.html { render :action => :edit }
+ format.api { render_validation_errors(@user) }
+ end
end
rescue ::ActionController::RedirectBackError
redirect_to :controller => 'users', :action => 'edit', :id => @user
end
+ verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
+ def destroy
+ @user.destroy
+ respond_to do |format|
+ format.html { redirect_to(users_url) }
+ format.api { head :ok }
+ end
+ end
+
def edit_membership
- @user = User.find(params[:id])
@membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
@membership.save if request.post?
respond_to do |format|
@@ -236,7 +268,6 @@
end
def destroy_membership
- @user = User.find(params[:id])
@membership = Member.find(params[:membership_id])
if request.post? && @membership.deletable?
@membership.destroy
@@ -246,4 +277,17 @@
format.js { render(:update) {|page| page.replace_html "tab-content-memberships", :partial => 'users/memberships'} }
end
end
+
+ private
+
+ def find_user
+ if params[:id] == 'current'
+ require_login || return
+ @user = User.current
+ else
+ @user = User.find(params[:id])
+ end
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/watchers_controller.rb
--- a/app/controllers/watchers_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/watchers_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -76,21 +76,13 @@
def set_watcher(user, watching)
@watched.set_watcher(user, watching)
- if params[:replace].present?
- if params[:replace].is_a? Array
- replace_ids = params[:replace]
- else
- replace_ids = [params[:replace]]
- end
- else
- replace_ids = ['watcher']
- end
respond_to do |format|
format.html { redirect_to :back }
format.js do
render(:update) do |page|
- replace_ids.each do |replace_id|
- page.replace_html replace_id, watcher_link(@watched, user, :replace => replace_ids)
+ c = watcher_css(@watched)
+ page.select(".#{c}").each do |item|
+ page.replace_html item, watcher_link(@watched, user)
end
end
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/wiki_controller.rb
--- a/app/controllers/wiki_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/wiki_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -1,16 +1,16 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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.
@@ -34,23 +34,27 @@
class WikiController < ApplicationController
default_search_scope :wiki_pages
before_filter :find_wiki, :authorize
+ before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
-
- verify :method => :post, :only => [:protect], :redirect_to => { :action => :show }
helper :attachments
- include AttachmentsHelper
+ include AttachmentsHelper
helper :watchers
# List of pages, sorted alphabetically and by parent (hierarchy)
def index
- load_pages_grouped_by_date_without_content
+ load_pages_for_index
+ @pages_by_parent_id = @pages.group_by(&:parent_id)
+ end
+
+ # List of page, by last update
+ def date_index
+ load_pages_for_index
+ @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
end
# display a page (in editing mode if it doesn't exist)
def show
- page_title = params[:id]
- @page = @wiki.find_or_new_page(page_title)
if @page.new_record?
if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
edit
@@ -79,13 +83,12 @@
@editable = editable?
render :action => 'show'
end
-
+
# edit an existing page or a new one
def edit
- @page = @wiki.find_or_new_page(params[:id])
return render_403 unless editable?
@page.content = WikiContent.new(:page => @page) if @page.new_record?
-
+
@content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@@ -93,18 +96,14 @@
# To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version
- rescue ActiveRecord::StaleObjectError
- # Optimistic locking exception
- flash[:error] = l(:notice_locking_conflict)
end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
# Creates a new page or updates an existing one
def update
- @page = @wiki.find_or_new_page(params[:id])
return render_403 unless editable?
@page.content = WikiContent.new(:page => @page) if @page.new_record?
-
+
@content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@@ -125,11 +124,14 @@
render_attachment_warning_if_needed(@page)
call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
redirect_to :action => 'show', :project_id => @project, :id => @page.title
+ else
+ render :action => 'edit'
end
rescue ActiveRecord::StaleObjectError
# Optimistic locking exception
- flash[:error] = l(:notice_locking_conflict)
+ flash.now[:error] = l(:notice_locking_conflict)
+ render :action => 'edit'
end
# rename a page
@@ -143,7 +145,8 @@
redirect_to :action => 'show', :project_id => @project, :id => @page.title
end
end
-
+
+ verify :method => :post, :only => :protect, :redirect_to => { :action => :show }
def protect
@page.update_attribute :protected, params[:protected]
redirect_to :action => 'show', :project_id => @project, :id => @page.title
@@ -153,8 +156,8 @@
def history
@version_count = @page.content.versions.count
@version_pages = Paginator.new self, @version_count, per_page_option, params['p']
- # don't load text
- @versions = @page.content.versions.find :all,
+ # don't load text
+ @versions = @page.content.versions.find :all,
:select => "id, author_id, comments, updated_on, version",
:order => 'version DESC',
:limit => @version_pages.items_per_page + 1,
@@ -162,12 +165,12 @@
render :layout => false if request.xhr?
end
-
+
def diff
@diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff
end
-
+
def annotate
@annotate = @page.annotate(params[:version])
render_404 unless @annotate
@@ -178,7 +181,7 @@
# Children can be either set as root pages, removed or reassigned to another parent page
def destroy
return render_403 unless editable?
-
+
@descendants_count = @page.descendants.size
if @descendants_count > 0
case params[:todo]
@@ -214,10 +217,6 @@
end
end
- def date_index
- load_pages_grouped_by_date_without_content
- end
-
def preview
page = @wiki.find_page(params[:id])
# page is nil when previewing a new page
@@ -238,7 +237,7 @@
end
private
-
+
def find_wiki
@project = Project.find(params[:project_id])
@wiki = @project.wiki
@@ -246,13 +245,27 @@
rescue ActiveRecord::RecordNotFound
render_404
end
-
+
+ # Finds the requested page or a new page if it doesn't exist
+ def find_existing_or_new_page
+ @page = @wiki.find_or_new_page(params[:id])
+ if @wiki.page_found_with_redirect?
+ redirect_to params.update(:id => @page.title)
+ end
+ end
+
# Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page
@page = @wiki.find_page(params[:id])
- render_404 if @page.nil?
+ if @page.nil?
+ render_404
+ return
+ end
+ if @wiki.page_found_with_redirect?
+ redirect_to params.update(:id => @page.title)
+ end
end
-
+
# Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page)
page.editable_by?(User.current)
@@ -265,13 +278,7 @@
helper.instance_method(:initial_page_content).bind(self).call(page)
end
- # eager load information about last updates, without loading text
- def load_pages_grouped_by_date_without_content
- @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
- :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
- :order => 'title'
- @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
- @pages_by_parent_id = @pages.group_by(&:parent_id)
+ def load_pages_for_index
+ @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
end
-
end
diff -r b9aebdd7dd40 -r 7eba09d624db app/controllers/workflows_controller.rb
--- a/app/controllers/workflows_controller.rb Thu Jul 14 10:46:20 2011 +0100
+++ b/app/controllers/workflows_controller.rb Thu Jul 14 10:50:53 2011 +0100
@@ -32,14 +32,17 @@
if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
- (params[:issue_status] || []).each { |old, news|
- news.each { |new|
- @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
+ (params[:issue_status] || []).each { |status_id, transitions|
+ transitions.each { |new_status_id, options|
+ author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
+ assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
+ @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
}
}
if @role.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker
+ return
end
end
@@ -48,6 +51,14 @@
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.find(:all, :order => 'position')
+
+ if @tracker && @role && @statuses.any?
+ workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id})
+ @workflows = {}
+ @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
+ @workflows['author'] = workflows.select {|w| w.author}
+ @workflows['assignee'] = workflows.select {|w| w.assignee}
+ end
end
def copy
diff -r b9aebdd7dd40 -r 7eba09d624db app/helpers/.svn/all-wcprops
--- a/app/helpers/.svn/all-wcprops Thu Jul 14 10:46:20 2011 +0100
+++ b/app/helpers/.svn/all-wcprops Thu Jul 14 10:50:53 2011 +0100
@@ -1,239 +1,17 @@
K 25
svn:wc:ra_dav:version-url
-V 36
-/svn/!svn/ver/4391/trunk/app/helpers
+V 50
+/svn/!svn/ver/6202/branches/1.2-stable/app/helpers
END
-trackers_helper.rb
+search_helper.rb
K 25
svn:wc:ra_dav:version-url
-V 54
-/svn/!svn/ver/333/trunk/app/helpers/trackers_helper.rb
-END
-groups_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/2869/trunk/app/helpers/groups_helper.rb
-END
-issue_statuses_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/333/trunk/app/helpers/issue_statuses_helper.rb
-END
-roles_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 51
-/svn/!svn/ver/333/trunk/app/helpers/roles_helper.rb
-END
-sort_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 51
-/svn/!svn/ver/3618/trunk/app/helpers/sort_helper.rb
-END
-repositories_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 59
-/svn/!svn/ver/3659/trunk/app/helpers/repositories_helper.rb
-END
-admin_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 52
-/svn/!svn/ver/4080/trunk/app/helpers/admin_helper.rb
-END
-projects_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/3924/trunk/app/helpers/projects_helper.rb
-END
-account_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/333/trunk/app/helpers/account_helper.rb
-END
-calendars_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 56
-/svn/!svn/ver/4046/trunk/app/helpers/calendars_helper.rb
-END
-issue_categories_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 62
-/svn/!svn/ver/333/trunk/app/helpers/issue_categories_helper.rb
-END
-documents_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/333/trunk/app/helpers/documents_helper.rb
-END
-wiki_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 51
-/svn/!svn/ver/4375/trunk/app/helpers/wiki_helper.rb
-END
-enumerations_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/333/trunk/app/helpers/enumerations_helper.rb
-END
-issues_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/4281/trunk/app/helpers/issues_helper.rb
-END
-gantt_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 52
-/svn/!svn/ver/4283/trunk/app/helpers/gantt_helper.rb
+V 67
+/svn/!svn/ver/6202/branches/1.2-stable/app/helpers/search_helper.rb
END
queries_helper.rb
K 25
svn:wc:ra_dav:version-url
-V 54
-/svn/!svn/ver/4387/trunk/app/helpers/queries_helper.rb
+V 68
+/svn/!svn/ver/6175/branches/1.2-stable/app/helpers/queries_helper.rb
END
-mail_handler_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 59
-/svn/!svn/ver/1584/trunk/app/helpers/mail_handler_helper.rb
-END
-watchers_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/3579/trunk/app/helpers/watchers_helper.rb
-END
-my_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 48
-/svn/!svn/ver/333/trunk/app/helpers/my_helper.rb
-END
-members_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/333/trunk/app/helpers/members_helper.rb
-END
-welcome_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/333/trunk/app/helpers/welcome_helper.rb
-END
-workflows_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 56
-/svn/!svn/ver/1914/trunk/app/helpers/workflows_helper.rb
-END
-journals_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/4062/trunk/app/helpers/journals_helper.rb
-END
-reports_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/629/trunk/app/helpers/reports_helper.rb
-END
-custom_fields_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 60
-/svn/!svn/ver/3675/trunk/app/helpers/custom_fields_helper.rb
-END
-settings_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/4222/trunk/app/helpers/settings_helper.rb
-END
-timelog_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 54
-/svn/!svn/ver/3708/trunk/app/helpers/timelog_helper.rb
-END
-users_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 52
-/svn/!svn/ver/4230/trunk/app/helpers/users_helper.rb
-END
-issue_moves_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/3936/trunk/app/helpers/issue_moves_helper.rb
-END
-application_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/4391/trunk/app/helpers/application_helper.rb
-END
-auth_sources_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/333/trunk/app/helpers/auth_sources_helper.rb
-END
-search_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 53
-/svn/!svn/ver/4353/trunk/app/helpers/search_helper.rb
-END
-messages_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 55
-/svn/!svn/ver/3373/trunk/app/helpers/messages_helper.rb
-END
-versions_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 54
-/svn/!svn/ver/955/trunk/app/helpers/versions_helper.rb
-END
-issue_relations_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 61
-/svn/!svn/ver/506/trunk/app/helpers/issue_relations_helper.rb
-END
-boards_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 52
-/svn/!svn/ver/529/trunk/app/helpers/boards_helper.rb
-END
-attachments_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 58
-/svn/!svn/ver/2116/trunk/app/helpers/attachments_helper.rb
-END
-news_helper.rb
-K 25
-svn:wc:ra_dav:version-url
-V 50
-/svn/!svn/ver/333/trunk/app/helpers/news_helper.rb
-END
diff -r b9aebdd7dd40 -r 7eba09d624db app/helpers/.svn/entries
--- a/app/helpers/.svn/entries Thu Jul 14 10:46:20 2011 +0100
+++ b/app/helpers/.svn/entries Thu Jul 14 10:50:53 2011 +0100
@@ -1,14 +1,14 @@
10
dir
-4411
-http://redmine.rubyforge.org/svn/trunk/app/helpers
+6270
+http://redmine.rubyforge.org/svn/branches/1.2-stable/app/helpers
http://redmine.rubyforge.org/svn
-2010-11-11T13:39:14.764400Z
-4391
+2011-07-09T11:26:35.866966Z
+6202
jplang
@@ -32,7 +32,7 @@
-2010-09-23T14:37:44.431779Z
+2011-07-14T09:24:09.000000Z
e1b19c2c81df384b2026001d1d9605fd
2007-03-12T17:59:02.654744Z
333
@@ -66,7 +66,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
ab0af291fb143223852a6edddc64b74b
2009-09-12T08:36:46.650954Z
2869
@@ -100,7 +100,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
0cd3093356b7034ee950ca327fc7aabc
2007-03-12T17:59:02.654744Z
333
@@ -134,7 +134,7 @@
-2010-09-23T14:37:44.431779Z
+2011-07-14T09:24:09.000000Z
69869e026dc6cbacc618214e4bb13b1b
2007-03-12T17:59:02.654744Z
333
@@ -168,10 +168,10 @@
-2010-09-23T14:37:44.431779Z
-491ead5828edb57adcd7333943656c94
-2010-03-27T16:55:20.312262Z
-3618
+2011-07-14T09:24:21.000000Z
+580d9b0753045bc89e5a92dfb9bccc65
+2011-04-03T14:09:22.655792Z
+5303
jplang
has-props
@@ -194,7 +194,7 @@
-6469
+6246
repositories_helper.rb
file
@@ -202,11 +202,11 @@
-2010-09-24T11:56:52.900009Z
-d617582e4bc6a3eedbc4f37f8fa3d509
-2010-04-11T15:18:49.769279Z
-3659
-jplang
+2011-07-14T09:24:21.000000Z
+bb401adbfcec298b2731e4e1fc4fe652
+2011-05-18T02:45:35.322493Z
+5830
+tmaruyama
has-props
@@ -228,7 +228,7 @@
-7654
+10966
admin_helper.rb
file
@@ -236,7 +236,7 @@
-2010-09-24T12:48:25.903794Z
+2011-07-14T09:24:09.000000Z
258ebc9ad13b3111585e5118ec607d1b
2010-09-10T23:07:10.817821Z
4080
@@ -270,11 +270,11 @@
-2010-09-23T14:37:44.427784Z
-19efbd2b30f44f233d5140437e2707a0
-2010-08-08T07:07:20.961363Z
-3924
-jbbarth
+2011-07-14T09:24:21.000000Z
+a0bf71359447b66a404f8911ca669a1c
+2011-05-18T11:13:02.791261Z
+5849
+tmaruyama
has-props
@@ -296,7 +296,7 @@
-5204
+5187
account_helper.rb
file
@@ -304,7 +304,7 @@
-2010-09-23T14:37:44.423776Z
+2011-07-14T09:24:09.000000Z
42d20ee00a3c45e3411634dbb09e2447
2007-03-12T17:59:02.654744Z
333
@@ -338,33 +338,33 @@
-2010-09-24T12:48:25.903794Z
-c8780c65337211f34097d74a8c3c9f6e
-2010-08-26T16:37:26.575205Z
-4046
-edavis10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1462
+2011-07-14T09:24:21.000000Z
+3fc9041a6dc70d35c640c38cd1edbbc8
+2011-04-03T14:01:32.419875Z
+5301
+jplang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1216
issue_categories_helper.rb
file
@@ -372,7 +372,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
1257aafe6669c839ab46dac2b2732ae0
2007-03-12T17:59:02.654744Z
333
@@ -406,7 +406,7 @@
-2010-09-23T14:37:44.423776Z
+2011-07-14T09:24:09.000000Z
ceb0fce7a4c271df3ae182c29caf9c03
2007-03-12T17:59:02.654744Z
333
@@ -440,10 +440,10 @@
-2010-11-19T13:04:46.900732Z
-3e6762604b5e9a201b7a7bb2edc1f78f
-2010-11-06T14:30:32.528294Z
-4375
+2011-07-14T09:24:21.000000Z
+a93e6c0c0834a0700ecd23ba24bf4102
+2011-03-10T19:44:32.117142Z
+5080
jplang
has-props
@@ -466,7 +466,7 @@
-2297
+1407
enumerations_helper.rb
file
@@ -474,7 +474,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
fc5ec20dd0ca3ce1d954b219417eff70
2007-03-12T17:59:02.654744Z
333
@@ -508,11 +508,11 @@
-2010-11-19T13:04:46.900732Z
-b5569bf5b4ba507a522f4e371505ae0c
-2010-10-22T22:29:32.969473Z
-4281
-jplang
+2011-07-14T09:24:21.000000Z
+f2465c49d740ce016b80c6035d7df2c4
+2011-05-18T02:45:59.814275Z
+5831
+tmaruyama
has-props
@@ -534,7 +534,7 @@
-10075
+12736
gantt_helper.rb
file
@@ -542,10 +542,10 @@
-2010-11-19T13:04:46.900732Z
-dfac5226f31c3c232d7dcc9416172071
-2010-10-23T09:08:55.877887Z
-4283
+2011-07-14T09:24:21.000000Z
+65d9a1166814eb63d467373051bf0b62
+2011-04-03T14:01:32.419875Z
+5301
jplang
@@ -568,7 +568,7 @@
-1988
+1492
queries_helper.rb
file
@@ -576,10 +576,10 @@
-2010-11-19T13:04:46.900732Z
-6b997d023cc081b101be1949eb18f893
-2010-11-07T15:38:51.908839Z
-4387
+2011-07-14T09:28:10.000000Z
+1151cd9213f891f7041f6ff0bf3ce39d
+2011-07-03T15:58:02.977468Z
+6175
jplang
has-props
@@ -602,7 +602,7 @@
-3722
+3845
mail_handler_helper.rb
file
@@ -610,7 +610,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
c79faf6237abac40fabce0eacbfbb4cb
2008-06-25T19:25:28.386590Z
1584
@@ -644,10 +644,10 @@
-2010-09-23T14:37:44.431779Z
-fc71d3a83fe0178e0c6d9519c7a62dde
-2010-03-13T17:45:41.194736Z
-3579
+2011-07-14T09:24:21.000000Z
+809ed0d1d7e143a2b6f4c695781d4dc0
+2011-04-05T12:09:15.508559Z
+5320
jplang
has-props
@@ -670,7 +670,7 @@
-2905
+2688
my_helper.rb
file
@@ -678,7 +678,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
d7134d76eff99aef107d8930903b10e0
2007-03-12T17:59:02.654744Z
333
@@ -712,7 +712,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
cc94b2fd5c6a87acac13bbe6e91bd39a
2007-03-12T17:59:02.654744Z
333
@@ -746,7 +746,7 @@
-2010-09-23T14:37:44.431779Z
+2011-07-14T09:24:09.000000Z
2d03eb3683f312ec26736c696319ec76
2007-03-12T17:59:02.654744Z
333
@@ -780,7 +780,7 @@
-2010-09-23T14:37:44.431779Z
+2011-07-14T09:24:09.000000Z
4f7bcbe149363ecb18080e3ce6c3f761
2008-09-28T12:03:17.584169Z
1914
@@ -814,7 +814,7 @@
-2010-09-24T12:48:25.903794Z
+2011-07-14T09:24:09.000000Z
b64edde44bceed7fb0911f87dba971aa
2010-09-05T22:57:20.669640Z
4062
@@ -848,11 +848,11 @@
-2010-09-23T14:37:44.431779Z
-9daafcfffa933849b3ee09fe5fd7b0cc
-2007-08-13T17:00:59.400243Z
-629
-jplang
+2011-07-14T09:24:21.000000Z
+abbaa87dcc23e906723ca0778128bae4
+2011-05-18T11:13:45.451188Z
+5850
+tmaruyama
has-props
@@ -874,7 +874,7 @@
-1265
+1262
custom_fields_helper.rb
file
@@ -882,11 +882,11 @@
-2010-09-23T14:37:44.423776Z
-97753365c8eb76a948d7417d5db31079
-2010-04-16T15:34:05.970144Z
-3675
-edavis10
+2011-07-14T09:24:21.000000Z
+3aab3283e46880f443fed09b975f3d7f
+2011-04-07T20:49:33.971753Z
+5356
+jplang
has-props
@@ -908,7 +908,7 @@
-5322
+5840
settings_helper.rb
file
@@ -916,11 +916,11 @@
-2010-11-19T13:04:46.900732Z
-868d0dc19e332ae2c817321637a8e31f
-2010-09-28T21:09:06.467392Z
-4222
-edavis10
+2011-07-14T09:24:21.000000Z
+da8c43c261cd527067440f75a242c091
+2011-05-29T12:06:05.086159Z
+5961
+jplang
has-props
@@ -942,7 +942,7 @@
-3858
+3937
timelog_helper.rb
file
@@ -950,7 +950,7 @@
-2010-09-23T14:37:44.431779Z
+2011-07-14T09:24:09.000000Z
1888fd2d4a1be5fa0d6ad8a63238e2b4
2010-04-30T12:18:11.536180Z
3708
@@ -978,13 +978,47 @@
6636
+users_helper.rb
+file
+
+
+
+
+2011-07-14T09:24:09.000000Z
+1bedb4287035a6f89074da0b37640c28
+2010-12-12T14:25:23.262992Z
+4497
+jplang
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2767
+
issue_moves_helper.rb
file
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
66e99bd3af036c92a773a91e92a725f9
2010-08-11T14:42:10.119704Z
3936
@@ -1012,51 +1046,17 @@
28
-users_helper.rb
-file
-
-
-
-
-2010-11-19T13:04:46.900732Z
-01b097606863e1e2938e7222d07fc2b7
-2010-09-30T18:22:46.611444Z
-4230
-edavis10
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2644
-
application_helper.rb
file
-2010-11-19T13:04:46.900732Z
-a9ac6edf6104b93a669ba1b0705f4fc6
-2010-11-11T13:39:14.764400Z
-4391
-jplang
+2011-07-14T09:24:21.000000Z
+639bb5f1e90caa8a4d6bb8029ab55905
+2011-05-18T02:46:24.994751Z
+5832
+tmaruyama
has-props
@@ -1078,7 +1078,7 @@
-34105
+35515
auth_sources_helper.rb
file
@@ -1086,7 +1086,7 @@
-2010-09-23T14:37:44.423776Z
+2011-07-14T09:24:09.000000Z
19759b6e665f9063140da8ac473d9e31
2007-03-12T17:59:02.654744Z
333
@@ -1120,10 +1120,10 @@
-2010-11-19T13:04:46.900732Z
-dedb3c62af67e076703aa2f60c97fb2b
-2010-11-01T12:55:15.292443Z
-4353
+2011-07-14T09:28:10.000000Z
+dace0a8b177ecab45cf16c82bd977364
+2011-07-09T11:26:35.866966Z
+6202
jplang
has-props
@@ -1146,7 +1146,7 @@
-2668
+2669
messages_helper.rb
file
@@ -1154,10 +1154,10 @@
-2010-09-23T14:37:44.427784Z
-70db854f3fd0a38d203a65c44d93bb13
-2010-02-06T12:54:13.653502Z
-3373
+2011-07-14T09:24:09.000000Z
+d083581ae234853db09e79e4e88d6ad3
+2011-01-23T17:02:10.030897Z
+4760
jplang
has-props
@@ -1180,41 +1180,7 @@
-1364
-
-versions_helper.rb
-file
-
-
-
-
-2010-09-23T14:37:44.431779Z
-fd18226266f3e53f6af000ac07a13313
-2007-12-07T10:26:07.864320Z
-955
-jplang
-has-props
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2170
+823
issue_relations_helper.rb
file
@@ -1222,7 +1188,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
fef3a97e6644b418b44f9551aa65af95
2007-05-05T13:22:27.245135Z
506
@@ -1250,13 +1216,47 @@
1017
+versions_helper.rb
+file
+
+
+
+
+2011-07-14T09:24:21.000000Z
+18e0206c3b8a4fb260548f58b75c7fa9
+2011-03-20T21:09:48.299058Z
+5180
+jplang
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2151
+
boards_helper.rb
file
-2010-09-23T14:37:44.423776Z
+2011-07-14T09:24:09.000000Z
0ca8f33522734ee0417089366037a7cb
2007-05-13T17:09:56.765659Z
529
@@ -1290,11 +1290,11 @@
-2010-09-23T14:37:44.423776Z
-6e15ada8c772d8daf8062cec2885ad9c
-2008-12-09T16:54:46.963649Z
-2116
-jplang
+2011-07-14T09:24:21.000000Z
+a2546fe896ad77351ab052f113afd012
+2011-05-07T05:51:39.224805Z
+5681
+tmaruyama
has-props
@@ -1316,7 +1316,7 @@
-1367
+1731
news_helper.rb
file
@@ -1324,7 +1324,7 @@
-2010-09-23T14:37:44.427784Z
+2011-07-14T09:24:09.000000Z
d808f6794a2fa7cd059ed56d5c8d1b28
2007-03-12T17:59:02.654744Z
333
diff -r b9aebdd7dd40 -r 7eba09d624db app/helpers/.svn/text-base/application_helper.rb.svn-base
--- a/app/helpers/.svn/text-base/application_helper.rb.svn-base Thu Jul 14 10:46:20 2011 +0100
+++ b/app/helpers/.svn/text-base/application_helper.rb.svn-base Thu Jul 14 10:50:53 2011 +0100
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2010 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -63,7 +63,7 @@
# Displays a link to +issue+ with its subject.
# Examples:
- #
+ #
# link_to_issue(issue) # => Defect #6: This is the subject
# link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
# link_to_issue(issue, :subject => false) # => Defect #6
@@ -80,7 +80,7 @@
subject = truncate(subject, :length => options[:truncate])
end
end
- s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
+ s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
:class => issue.css_classes,
:title => title
s << ": #{h subject}" if subject
@@ -104,13 +104,29 @@
# * :text - Link text (default to the formatted revision)
def link_to_revision(revision, project, options={})
text = options.delete(:text) || format_revision(revision)
+ rev = revision.respond_to?(:identifier) ? revision.identifier : revision
- link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => revision}, :title => l(:label_revision_id, revision))
+ link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev},
+ :title => l(:label_revision_id, format_revision(revision)))
+ end
+
+ # Generates a link to a message
+ def link_to_message(message, options={}, html_options = nil)
+ link_to(
+ h(truncate(message.subject, :length => 60)),
+ { :controller => 'messages', :action => 'show',
+ :board_id => message.board_id,
+ :id => message.root,
+ :r => (message.parent_id && message.id),
+ :anchor => (message.parent_id ? "message-#{message.id}" : nil)
+ }.merge(options),
+ html_options
+ )
end
# Generates a link to a project if active
# Examples:
- #
+ #
# link_to_project(project) # => link to the specified project overview
# link_to_project(project, :action=>'settings') # => link to project settings
# link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
@@ -144,15 +160,15 @@
html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
link_to name, {}, html_options
end
-
+
def format_activity_title(text)
h(truncate_single_line(text, :length => 100))
end
-
+
def format_activity_day(date)
date == Date.today ? l(:label_today).titleize : format_date(date)
end
-
+
def format_activity_description(text)
h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "
")
end
@@ -164,29 +180,29 @@
h("#{version.project} - #{version}")
end
end
-
+
def due_date_distance_in_words(date)
if date
l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
end
end
- def render_page_hierarchy(pages, node=nil)
+ def render_page_hierarchy(pages, node=nil, options={})
content = ''
if pages[node]
content << "