From 3599d4c3b506b18db905a5fccdf4ed638a323c72 Mon Sep 17 00:00:00 2001 From: CI Date: Wed, 5 Apr 2017 00:37:40 +0000 Subject: [PATCH 01/29] Update reference to OpenProject-Translations --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index df88d057bc..e0c913d680 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,7 +60,7 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: 9ceb4a1d320459636fd74dcaf433919ee533d18d + revision: 1042c2e55f57c9e8ea42b66cfbf1e35932c0038c branch: release/6.1 specs: openproject-translations (6.1.6) From ac9d9feb57bd9692a14393b096a43c8c699d2573 Mon Sep 17 00:00:00 2001 From: CI Date: Thu, 6 Apr 2017 00:37:27 +0000 Subject: [PATCH 02/29] Update reference to OpenProject-Translations --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index e0c913d680..d4eacdb88b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,7 +60,7 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: 1042c2e55f57c9e8ea42b66cfbf1e35932c0038c + revision: 042daaefd021d7697c51413756ab578ccaef4899 branch: release/6.1 specs: openproject-translations (6.1.6) From 69ecc9ded77e3484a0ccb70548393248138bbd24 Mon Sep 17 00:00:00 2001 From: CI Date: Fri, 7 Apr 2017 00:37:26 +0000 Subject: [PATCH 03/29] Update reference to OpenProject-Translations --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index d4eacdb88b..b63a3af1e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -251,7 +251,7 @@ GEM representable (~> 2.0) uber docile (1.1.5) - domain_name (0.5.20170223) + domain_name (0.5.20170404) unf (>= 0.0.5, < 1.0.0) enumerable-lazy (0.0.1) equalizer (0.0.11) From 73e4a438c427742dbeb54d51e7bc3662b66eebd2 Mon Sep 17 00:00:00 2001 From: CI Date: Mon, 10 Apr 2017 00:48:25 +0000 Subject: [PATCH 04/29] Update reference to OpenProject-Translations --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index b63a3af1e7..757d709595 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,7 +60,7 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: 042daaefd021d7697c51413756ab578ccaef4899 + revision: f58a67ba5d3b743cd4d507c44dcd9cc82c669e1d branch: release/6.1 specs: openproject-translations (6.1.6) From 1cc2758ccb073cff9be69264828cdd5453ed6f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 10 Apr 2017 09:05:24 +0200 Subject: [PATCH 05/29] [docs] Add steps for incoming-mails for packaged installation [ci skip] --- docs/configuration/incoming-emails.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/configuration/incoming-emails.md b/docs/configuration/incoming-emails.md index 43c4501846..84e0bbffa1 100644 --- a/docs/configuration/incoming-emails.md +++ b/docs/configuration/incoming-emails.md @@ -9,7 +9,14 @@ Receiving emails is done via a rake task that fetches emails from an email serve ### IMAP The rake task `redmine:email:receive_imap` fetches emails via IMAP and parses them. -Example: + +**Packaged installation** + +```bash +openproject run bundle exec rake redmine:email:receive_imap host='imap.gmail.com' username='test_user' password='password' port=993 ssl=true allow_override=type,project project=test_project +``` + +**Manual installation** ```bash bundle exec rake redmine:email:receive_imap host='imap.gmail.com' username='test_user' password='password' port=993 ssl=true allow_override=type,project project=test_project @@ -42,7 +49,14 @@ Available arguments that change how the work packages are handled: ### POP3 The rake task `redmine:email:receive_pop3` fetches emails via IMAP and parses them. -Example: +**Packaged installation** + +```bash +openproject run bundle exec rake redmine:email:receive_imap host='imap.gmail.com' username='test_user' password='password' port=993 ssl=true allow_override=type,project project=test_project +``` + +**Manual installation** + ```bash bundle exec rake redmine:email:receive_pop3 host='pop.gmail.com' username='test_user' password='password' port=995 allow_override=priority ``` From 2c958a90314b26784ce233810e2b91622b7269c6 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Mon, 12 Jun 2017 16:33:25 +0200 Subject: [PATCH 06/29] remove plugin references from Gemfile.lock --- Gemfile.lock | 205 --------------------------------------------------- 1 file changed, 205 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d698f70da8..256d2138b4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -103,129 +103,9 @@ GIT activesupport (>= 3.0) rspec-mocks (>= 2.99, < 4.0) -PATH - remote: ../ownplugins/omniauth-openid-connect - specs: - omniauth-openid-connect (0.2.0) - addressable (~> 2.3) - omniauth (~> 1.1) - openid_connect (~> 0.8.0) - -PATH - remote: ../ownplugins/omniauth-openid_connect-providers - specs: - omniauth-openid_connect-providers (0.1.0) - omniauth-openid-connect (>= 0.2.0) - -PATH - remote: ../plugins/openproject-auth_plugins - specs: - openproject-auth_plugins (7.0.2) - omniauth (~> 1.0) - rails (~> 5.0) - -PATH - remote: ../plugins/openproject-backlogs - specs: - openproject-backlogs (7.0.2) - acts_as_silent_list (~> 3.0.0) - openproject-pdf_export (= 7.0.2) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-costs - specs: - openproject-costs (7.0.2) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-documents - specs: - openproject-documents (7.0.2) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-github_integration - specs: - openproject-github_integration (7.0.2) - openproject-webhooks (~> 7.0.2) - rails (~> 5.0) - -PATH - remote: ../plugins/openproject-global_roles - specs: - openproject-global_roles (7.0.2) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-local_avatars - specs: - openproject-local_avatars (7.0.2) - rails (~> 5.0) - rmagick (~> 2.15.4) - -PATH - remote: ../plugins/openproject-meeting - specs: - openproject-meeting (7.0.2) - icalendar (~> 2.3.0) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-my_project_page - specs: - openproject-my_project_page (7.0.2) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-openid_connect - specs: - openproject-openid_connect (7.0.2) - lobby_boy (~> 0.1) - omniauth-openid_connect-providers (~> 0.1) - openproject-auth_plugins (~> 7.0) - rails (~> 5.0) - -PATH - remote: ../plugins/openproject-pdf_export - specs: - openproject-pdf_export (7.0.2) - prawn (~> 2.2) - rails (~> 5.0.0) - -PATH - remote: ../plugins/openproject-reporting - specs: - openproject-reporting (7.0.2) - jquery-tablesorter (~> 1.22.3) - openproject-costs (= 7.0.2) - rails (~> 5.0.0) - reporting_engine (>= 1.1.0) - -PATH - remote: ../plugins/openproject-webhooks - specs: - openproject-webhooks (7.0.2) - rails (~> 5.0) - -PATH - remote: ../plugins/openproject-xls_export - specs: - openproject-xls_export (7.0.2) - rails (~> 5.0.0) - spreadsheet (~> 0.8.9) - -PATH - remote: ../plugins/reporting_engine - specs: - reporting_engine (7.0.2) - json - rails (~> 5.0.0) - GEM remote: https://rubygems.org/ specs: - Ascii85 (1.0.2) actioncable (5.0.3) actionpack (= 5.0.3) nio4r (>= 1.2, < 3.0) @@ -280,18 +160,15 @@ GEM tzinfo (~> 1.1) acts_as_list (0.9.5) activerecord (>= 3.0) - acts_as_silent_list (3.0.0) acts_as_tree (2.6.1) activerecord (>= 3.0.0) addressable (2.5.1) public_suffix (~> 2.0, >= 2.0.2) - afm (0.2.2) airbrake (5.1.0) airbrake-ruby (~> 1.1) airbrake-ruby (1.5.0) arel (7.1.4) ast (2.3.0) - attr_required (1.0.1) autoprefixer-rails (6.7.7.2) execjs awesome_nested_set (3.1.3) @@ -309,7 +186,6 @@ GEM ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) bcrypt (3.1.11) - bindata (2.4.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) bourbon (4.3.4) @@ -448,32 +324,21 @@ GEM grape (~> 0.3) gravatar_image_tag (1.2.0) hashdiff (0.3.4) - hashery (2.1.2) hashie (3.5.5) health_check (2.6.0) rails (>= 4.0) htmldiff (0.0.1) http-cookie (1.0.3) domain_name (~> 0.5) - httpclient (2.8.3) i18n (0.8.1) i18n-js (3.0.0) i18n (~> 0.6, >= 0.6.6) - icalendar (2.3.0) ice_nine (0.11.2) interception (0.5) ipaddress (0.8.3) iso8601 (0.9.1) jmespath (1.3.1) - jquery-tablesorter (1.22.7) - railties (>= 3.2, < 6) json (1.8.6) - json-jwt (1.7.2) - activesupport - bindata - multi_json (>= 1.3) - securecompare - url_safe_base64 json_spec (1.1.4) multi_json (~> 1.0) rspec (>= 2.0, < 4.0) @@ -488,10 +353,6 @@ GEM sass thor tilt - lobby_boy (0.1.2) - omniauth (~> 1.1) - omniauth-openid-connect (>= 0.2) - rails (>= 3.2.21) loofah (2.0.3) nokogiri (>= 1.5.9) mail (2.6.5) @@ -516,17 +377,6 @@ GEM nokogiri (1.7.2) mini_portile2 (~> 2.1.0) oj (3.0.6) - openid_connect (0.8.3) - activemodel - attr_required (>= 0.0.5) - json (>= 1.4.3) - json-jwt (>= 0.5.5) - rack-oauth2 (>= 1.0.0) - swd (>= 0.1.2) - tzinfo - validate_email - validate_url - webfinger (>= 0.0.2) openproject-token (1.0.0) activemodel (~> 5.0) parallel (1.11.1) @@ -538,14 +388,6 @@ GEM rack rake (>= 0.8.1) pdf-core (0.7.0) - pdf-inspector (1.0.2) - pdf-reader (>= 0.9.0) - pdf-reader (2.0.0) - Ascii85 (~> 1.0.0) - afm (~> 0.2.1) - hashery (~> 2.0) - ruby-rc4 - ttfunk pg (0.20.0) powerpack (0.1.1) prawn (2.2.2) @@ -579,12 +421,6 @@ GEM rack (>= 0.4) rack-attack (5.0.1) rack - rack-oauth2 (1.6.2) - activesupport (>= 2.3) - attr_required (>= 0.0.5) - httpclient (>= 2.4) - multi_json (>= 1.3.6) - rack (>= 1.1) rack-protection (2.0.0) rack rack-test (0.6.3) @@ -648,7 +484,6 @@ GEM mime-types (>= 1.16, < 3.0) netrc (~> 0.7) retriable (2.1.0) - rmagick (2.15.4) roar (1.0.4) representable (>= 2.0.1, < 2.4.0) rspec (3.5.0) @@ -686,9 +521,7 @@ GEM activesupport (>= 3.0.0) i18n iso8601 - ruby-ole (1.2.12.1) ruby-progressbar (1.8.1) - ruby-rc4 (0.1.5) rubyzip (1.2.1) safe_yaml (1.0.4) sass (3.5.0.pre.rc.1) @@ -702,7 +535,6 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - securecompare (1.0.0) selenium-webdriver (2.53.4) childprocess (~> 0.5) rubyzip (~> 1.0) @@ -716,8 +548,6 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) - spreadsheet (0.8.9) - ruby-ole (>= 1.0) sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -728,12 +558,6 @@ GEM sqlite3 (1.3.11) stringex (2.7.1) svg-graph (2.1.0) - swd (1.0.1) - activesupport (>= 3) - attr_required (>= 0.0.5) - httpclient (>= 2.4) - i18n - json (>= 1.4.3) syck (1.3.0) sys-filesystem (1.1.7) ffi @@ -761,13 +585,6 @@ GEM unicorn-worker-killer (0.4.4) get_process_mem (~> 0) unicorn (>= 4, < 6) - url_safe_base64 (0.2.2) - validate_email (0.1.6) - activemodel (>= 3.0) - mail (>= 2.2.5) - validate_url (1.0.2) - activemodel (>= 3.0.0) - addressable virtus (1.0.5) axiom-types (~> 0.1) coercible (~> 1.0) @@ -777,10 +594,6 @@ GEM rack (>= 1.0) warden-basic_auth (0.2.1) warden (~> 1.2) - webfinger (1.0.2) - activesupport - httpclient (>= 2.4) - multi_json webmock (3.0.1) addressable (>= 2.3.6) crack (>= 0.3.2) @@ -856,27 +669,10 @@ DEPENDENCIES nokogiri (~> 1.7.2) oj (~> 3.0.6) omniauth! - omniauth-openid-connect! - omniauth-openid_connect-providers! - openproject-auth_plugins! - openproject-backlogs! - openproject-costs! - openproject-documents! - openproject-github_integration! - openproject-global_roles! - openproject-local_avatars! - openproject-meeting! - openproject-my_project_page! - openproject-openid_connect! - openproject-pdf_export! - openproject-reporting! openproject-token (~> 1.0.0) openproject-translations! - openproject-webhooks! - openproject-xls_export! parallel_tests (~> 2.14.0) passenger - pdf-inspector (~> 1.0.0) pg (~> 0.20.0) prawn (~> 2.2) prawn-table (~> 0.2.2) @@ -897,7 +693,6 @@ DEPENDENCIES rails_autolink (~> 1.1.6) rdoc (>= 2.4.2) reform (~> 1.2.6) - reporting_engine! request_store (~> 1.3.1) responders (~> 2.4) retriable (~> 2.1) From e28389128e40a0f3a8efe9f463d75018af4136e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 12 Jun 2017 16:30:44 +0200 Subject: [PATCH 07/29] Bundling with next version on release branch --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 256d2138b4..4d9b282569 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,10 +68,10 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: e2ac6c6659ab40cff9a127b80bb8d39438153c55 + revision: 5ce6b92a2e184f521fba05b8db1aabf2b61a553d branch: release/7.0 specs: - openproject-translations (7.0.2) + openproject-translations (7.0.3) crowdin-api (~> 0.4.1) mixlib-shellout (~> 2.1.0) rails (~> 5.0.0) From a7191746ecddae7c888ac1cd7af47bd6f4120adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 12 Jun 2017 16:30:44 +0200 Subject: [PATCH 08/29] Bump VERSION to 7.0.3 --- lib/open_project/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 96768f53ac..c9958bf145 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -34,7 +34,7 @@ module OpenProject module VERSION #:nodoc: MAJOR = 7 MINOR = 0 - PATCH = 2 + PATCH = 3 TINY = PATCH # Redmine compat # Used by semver to define the special version (if any). From 07a3cefbfad38dc72b505286880aab8ce01d14f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 13 Jun 2017 08:05:28 +0200 Subject: [PATCH 09/29] Create upgrading.md --- docs/operations/upgrading/manual/upgrading.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/operations/upgrading/manual/upgrading.md b/docs/operations/upgrading/manual/upgrading.md index ad390901d0..02a82c57b8 100644 --- a/docs/operations/upgrading/manual/upgrading.md +++ b/docs/operations/upgrading/manual/upgrading.md @@ -1,10 +1,14 @@ -# OpenProject 6.0.x to OpenProject 6.1 Debian/Ubuntu Upgrade Guide (Manual installation) +# OpenProject 6.x to OpenProject 7.x Debian/Ubuntu Upgrade Guide (Manual installation) -Please look at the steps in the section about the upgrade to OpenProject 6.0. OpenProject 6.x is being released under the branch `stable/6`. +Please look at the steps in the section about the upgrade to OpenProject 6.0. OpenProject 7.x is being released under the branch `stable/7`. The other steps are identical. + +### Frontend changes, bower is no longer required + +With OpenProject 7.0., we no longer depend on `bower` for some on the frontend assets. Please ensure you remove `/frontend/bower_components` and `/frontend/bower.json`. ### When running with MySQL: Required changes in sql_mode -If you're upgrading to OpenProject 6.1.x with a MySQL installation, you will need to update your database.yml to reflect some necessary changes to MySQL `sql_mode` made as part of the migration to Rails 5. Please see the `config/database.yml.example` file for more information. +If you're upgrading to OpenProject 7.x with a MySQL installation, you will need to update your database.yml to reflect some necessary changes to MySQL `sql_mode` made as part of the migration to Rails 5. Please see the `config/database.yml.example` file for more information. # OpenProject 5.0.x to OpenProject 6.0 Debian/Ubuntu Upgrade Guide From 0c112a617f9e7ff672164e0d354881a3acf0f8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 13 Jun 2017 09:33:01 +0200 Subject: [PATCH 10/29] Mind the semikolon [ci skip] --- app/assets/stylesheets/openproject/_plugins.scss.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/openproject/_plugins.scss.erb b/app/assets/stylesheets/openproject/_plugins.scss.erb index 7c77ed11e0..88eca61524 100644 --- a/app/assets/stylesheets/openproject/_plugins.scss.erb +++ b/app/assets/stylesheets/openproject/_plugins.scss.erb @@ -1,5 +1,5 @@ <% Redmine::Plugin.all.collect do |plugin| %> <% plugin.registered_global_assets[:css].each do |path| %> - @import "<%= path %>" + @import "<%= path %>"; <% end %> <% end %> From 16f0cace89d72de6e419c1cde0ce323fcc483176 Mon Sep 17 00:00:00 2001 From: ulferts Date: Tue, 13 Jun 2017 13:34:54 +0200 Subject: [PATCH 11/29] Fix/wp copy with cf (#5638) * fix copying cf values on wp copy * use angular copy form if only one wp copied [ci skip] --- app/models/work_package.rb | 11 +++---- .../wp-context-menu.controller.ts | 23 +++++++++++-- .../work_packages/table/context_menu_spec.rb | 5 +-- spec/models/work_package_spec.rb | 33 ++++++++++--------- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/app/models/work_package.rb b/app/models/work_package.rb index f2c6e2c506..f4665566ec 100644 --- a/app/models/work_package.rb +++ b/app/models/work_package.rb @@ -252,7 +252,7 @@ def self.event_url # after the wp is created. # As after_create is run before after_save, and journal creation is triggered by an # after_save hook, we rely on after_save and a specific version here. - after_save :reload_lock_and_timestamps, if: Proc.new { |wp| wp.lock_version == 0 } + after_save :reload_lock_and_timestamps, if: Proc.new { |wp| wp.lock_version.zero? } def self.done_ratio_disabled? Setting.work_package_done_ratio == 'disabled' @@ -286,11 +286,10 @@ def copy_from(arg, options = {}) # attributes don't come from form, so it's safe to force assign self.attributes = work_package.attributes.dup.except(*merged_options[:exclude]) self.parent_id = work_package.parent_id if work_package.parent_id - self.custom_field_values = - work_package.custom_field_values.inject({}) do |h, v| - h[v.custom_field_id] = work_package.custom_value_for(v.custom_field_id) - h - end + self.custom_field_values = work_package + .custom_values + .map { |cv| [cv.custom_field_id, cv.value] } + .to_h self.status = work_package.status work_package.watchers.each do |watcher| diff --git a/frontend/app/components/context-menus/wp-context-menu/wp-context-menu.controller.ts b/frontend/app/components/context-menus/wp-context-menu/wp-context-menu.controller.ts index 1c62542a12..e3c6b904ab 100644 --- a/frontend/app/components/context-menus/wp-context-menu/wp-context-menu.controller.ts +++ b/frontend/app/components/context-menus/wp-context-menu/wp-context-menu.controller.ts @@ -60,8 +60,8 @@ function wpContextMenuController($scope:any, }; $scope.triggerContextMenuAction = function (action:any, link:any) { - let table: WorkPackageTable; - let wp: WorkPackageResourceInterface; + let table:WorkPackageTable; + let wp:WorkPackageResourceInterface; switch (action) { case 'delete': @@ -72,6 +72,10 @@ function wpContextMenuController($scope:any, editSelectedWorkPackages(link); break; + case 'copy': + copySelectedWorkPackages(link); + break; + case 'relation-precedes': table = $scope.table; wp = $scope.row.object; @@ -125,6 +129,21 @@ function wpContextMenuController($scope:any, $state.transitionTo('work-packages.show.edit', params); } + function copySelectedWorkPackages(link:any) { + var selected = getSelectedWorkPackages(); + + if (selected.length > 1) { + $window.location.href = link; + return; + } + + var params = { + copiedFromWorkPackageId: selected[0].id + }; + + $state.transitionTo('work-packages.list.copy', params); + } + function getSelectedWorkPackages() { let workPackagefromContext = $scope.row.object; let selectedWorkPackages = wpTableSelection.getSelectedWorkPackages(); diff --git a/spec/features/work_packages/table/context_menu_spec.rb b/spec/features/work_packages/table/context_menu_spec.rb index 4faa97266e..4d9d674ef9 100644 --- a/spec/features/work_packages/table/context_menu_spec.rb +++ b/spec/features/work_packages/table/context_menu_spec.rb @@ -57,8 +57,9 @@ def goto_context_menu # Open Copy goto_context_menu menu.choose('Copy') - expect(page).to have_selector('h2', text: I18n.t(:button_copy)) - expect(page).to have_selector('a.issue', text: "##{work_package.id}") + # Split view open in copy state + expect(page).to have_selector('.work-packages--details', text: "New #{work_package.type}") + expect(page).to have_field('wp-new-inline-edit--field-subject', with: work_package.subject) # Open Delete goto_context_menu diff --git a/spec/models/work_package_spec.rb b/spec/models/work_package_spec.rb index cb1dd1eaa9..e1fad146bd 100644 --- a/spec/models/work_package_spec.rb +++ b/spec/models/work_package_spec.rb @@ -462,34 +462,32 @@ def stub_shared_versions(v = nil) describe '#copy_from' do let(:type) { FactoryGirl.create(:type_standard) } let(:project) { FactoryGirl.create(:project, types: [type]) } - let(:custom_field) { + let(:custom_field) do FactoryGirl.create(:work_package_custom_field, name: 'Database', field_format: 'list', possible_values: ['MySQL', 'PostgreSQL', 'Oracle'], is_required: true) - } + end + let(:bool_custom_field) do + FactoryGirl.create(:bool_wp_custom_field) + end let(:source) { FactoryGirl.build(:work_package) } let(:sink) { FactoryGirl.build(:work_package) } - before do - def self.change_custom_field_value(work_package, value) - work_package.custom_field_values = { custom_field.id => value } unless value.nil? - work_package.save - end - end - before do project.work_package_custom_fields << custom_field type.custom_fields << custom_field - source.save - end + project.work_package_custom_fields << bool_custom_field + type.custom_fields << bool_custom_field - before do source.project_id = project.id - change_custom_field_value(source, 'MySQL') + + source.custom_field_values = { custom_field.id => 'MySQL', + bool_custom_field.id => 'f' } + source.save end shared_examples_for 'work package copy' do @@ -530,18 +528,23 @@ def self.change_custom_field_value(work_package, value) shared_examples_for 'work package copy with custom field' do it_behaves_like 'work package copy' - context 'custom_field' do + context 'list custom_field' do subject { sink.custom_value_for(custom_field.id).value } it { is_expected.to eq('MySQL') } end + + context 'bool custom_field' do + subject { sink.custom_value_for(bool_custom_field.id).value } + + it { is_expected.to eq('f') } + end end context 'with project' do let(:project_id) { source.project_id } describe 'should copy project' do - before { sink.copy_from(source) } it_behaves_like 'work package copy with custom field' From 8e16ad70d63ede8b2d684aaa253260ba4141f0b4 Mon Sep 17 00:00:00 2001 From: heitorbc Date: Tue, 13 Jun 2017 19:39:23 -0300 Subject: [PATCH 12/29] Fix broken link in manual installation guide fixing problem on apt-get at installing Apache. [ci skip] --- docs/installation/manual/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/manual/README.md b/docs/installation/manual/README.md index 9379e4d216..95c2610290 100644 --- a/docs/installation/manual/README.md +++ b/docs/installation/manual/README.md @@ -259,7 +259,7 @@ Then, we prepare apache and passenger: ```bash [root@host] apt-get install -y apache2 libcurl4-gnutls-dev \ - apache2-threaded-dev libapr1-dev \ + apache2-dev libapr1-dev \ libaprutil1-dev [root@ubuntu] chmod o+x "/home/openproject" ``` From 6bb684a53119ad42c5d2bdce05ba612c739ababe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 14 Jun 2017 10:46:18 +0200 Subject: [PATCH 13/29] [25534] Fix needless escaping with jquery-ui (#5649) The `_.escape` was used for the typehead that was since replaced by ui-autocompleter, which uses a text node to insert the label: https://github.com/jquery/jquery-ui/blob/master/ui/widgets/autocomplete.js#L568 Thus the escape is no longer necessary. https://community.openproject.com/projects/openproject/work_packages/25534/activity?query_id=930 [ci skip] --- .../wp-relations-autocomplete.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.directive.ts b/frontend/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.directive.ts index c94f796ff4..2ff7271922 100644 --- a/frontend/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.directive.ts +++ b/frontend/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.directive.ts @@ -83,7 +83,7 @@ function wpRelationsAutocompleteDirective( function getIdentifier(workPackage:WorkPackageResourceInterface):string { if (workPackage) { - return _.escape(`#${workPackage.id} - ${workPackage.subject}`); + return `#${workPackage.id} - ${workPackage.subject}`; } else { return ''; } From f28e88e89ff6275a9f984899a210f054e791fe37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 14 Jun 2017 11:37:37 +0200 Subject: [PATCH 14/29] [25464] Optional additional_boot instructions to evaluate early The hashie warnings from 25464 are evalauted early on while bundler requires all necessary gems, so silencing them is not possible without modifications to the code, subject to be overridden on each release. Since there may be other instructions before Rails boots, let's add a simple `additional_boot.rb` functionality similary to the `additional_environment.rb`, that a user MAY use to provide these statements. https://community.openproject.com/projects/openproject/work_packages/25464/activity --- config/additional_boot.rb.example | 8 ++++++++ config/boot.rb | 7 +++++++ 2 files changed, 15 insertions(+) create mode 100644 config/additional_boot.rb.example diff --git a/config/additional_boot.rb.example b/config/additional_boot.rb.example new file mode 100644 index 0000000000..f63ae1cf69 --- /dev/null +++ b/config/additional_boot.rb.example @@ -0,0 +1,8 @@ +# Copy this file to additional_boot.rb and add any statements +# that should run prior to Rails booting. +# +# Example: +# +# Silence Hashie warnings in OpenProject 7.0.x +# require 'hashie' +# Hashie.logger = Logger.new(nil) diff --git a/config/boot.rb b/config/boot.rb index 6031f1c67b..ea7c852ee7 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -29,4 +29,11 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +# Load any local boot extras that is kept out of source control +# (e.g., silencing of deprecations) +if File.exists?(File.join(File.dirname(__FILE__), 'additional_boot.rb')) + instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_boot.rb')) +end + + require 'bundler/setup' # Set up gems listed in the Gemfile. From cbf6671402ed18553a80e78fd74f458f0fb38252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 14 Jun 2017 11:41:10 +0200 Subject: [PATCH 15/29] Housekeeping/strengthen specs (#5650) * Try to strengthen CF spec * Removing randomly failing old TL cuke [ci skip] --- .../timeline_work_package_show_view.feature | 59 ------------------- .../inplace_editor/custom_field_spec.rb | 2 +- .../work_packages/work_package_field.rb | 6 +- 3 files changed, 5 insertions(+), 62 deletions(-) delete mode 100644 features/timelines/timeline_work_package_show_view.feature diff --git a/features/timelines/timeline_work_package_show_view.feature b/features/timelines/timeline_work_package_show_view.feature deleted file mode 100644 index bc27b32a71..0000000000 --- a/features/timelines/timeline_work_package_show_view.feature +++ /dev/null @@ -1,59 +0,0 @@ -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2017 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2017 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# 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. -# -# See doc/COPYRIGHT.rdoc for more details. -#++ - -Feature: Timeline Work Package Show View - As a Project Member - I want edit planning elements to open in a new tab - - Background: - Given there is 1 user with: - | login | manager | - And there is a role "manager" - And the role "manager" may have the following rights: - | view_timelines | - | edit_timelines | - | view_work_packages | - And there is a project named "ecookbook" - And I am working in project "ecookbook" - And there is a timeline "Testline" for project "ecookbook" - And the project uses the following modules: - | timelines | - And the user "manager" is a "manager" - And there are the following work packages: - | Start date | Due date | description | responsible | Subject | - | 2012-01-01 | 2012-01-31 | #2 http://google.de | manager | January | - | 2012-02-01 | 2012-02-24 | Avocado Rincon | manager | February | - And I am already logged in as "manager" - - @javascript - Scenario: planning element click should show the plannin element - When I go to the page of the timeline "Testline" of the project called "ecookbook" - And I wait for timeline to load table - And I should see "January" - When I click on the Planning Element with name "January" - Then I should see "January" in the new window diff --git a/spec/features/work_packages/details/inplace_editor/custom_field_spec.rb b/spec/features/work_packages/details/inplace_editor/custom_field_spec.rb index b8ee1a14dc..491a4f6739 100644 --- a/spec/features/work_packages/details/inplace_editor/custom_field_spec.rb +++ b/spec/features/work_packages/details/inplace_editor/custom_field_spec.rb @@ -37,6 +37,7 @@ def expect_update(value, update_args) wp_field.set_value value wp_field.submit_by_enter if wp_field.field_type == 'input' wp_page.expect_notification(update_args) + wp_page.dismiss_notification! end describe 'long text' do @@ -107,7 +108,6 @@ def custom_value(value) wp_page.expect_attributes customField1: 'bar', customField2: 'X' - wp_page.dismiss_notification! end end diff --git a/spec/support/work_packages/work_package_field.rb b/spec/support/work_packages/work_package_field.rb index ea3d475204..1480795056 100644 --- a/spec/support/work_packages/work_package_field.rb +++ b/spec/support/work_packages/work_package_field.rb @@ -36,8 +36,10 @@ def element ## # Activate the field and check it opened correctly def activate! - element.find(trigger_link_selector).click - expect_active! + retry_block do + element.find(trigger_link_selector).click + expect_active! + end end def expect_state!(open:) From 9323ded10bb4071cd9034bedb36cbefc7391f4da Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 8 Jun 2017 17:04:30 +0200 Subject: [PATCH 16/29] add missing ) to watcher filter sql statement --- app/models/queries/work_packages/filter/watcher_filter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/queries/work_packages/filter/watcher_filter.rb b/app/models/queries/work_packages/filter/watcher_filter.rb index d30d64e33e..4ef7d09784 100644 --- a/app/models/queries/work_packages/filter/watcher_filter.rb +++ b/app/models/queries/work_packages/filter/watcher_filter.rb @@ -101,7 +101,7 @@ def where_self_watcher(user_id) (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='WorkPackage' - AND #{::Queries::Operators::Equals.sql_for_field [user_id], db_table, db_field} + AND #{::Queries::Operators::Equals.sql_for_field [user_id], db_table, db_field}) SQL end From 450508748de888b4035661e424747e35f0c8e660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 15 Jun 2017 07:20:16 +0200 Subject: [PATCH 17/29] Reference stable/7 [ci skip] --- docs/installation/manual/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/installation/manual/README.md b/docs/installation/manual/README.md index 95c2610290..571ce705f8 100644 --- a/docs/installation/manual/README.md +++ b/docs/installation/manual/README.md @@ -1,6 +1,6 @@ -# Manual installation of OpenProject 6.1 with Apache on Ubuntu 14.04. LTS +# Manual installation of OpenProject 7.0 with Apache on Ubuntu 14.04. LTS -This tutorial helps you to deploy OpenProject 6.1. Please, aware that: +This tutorial helps you to deploy OpenProject 7.0. Please, aware that: This guide requires that you have a clean Ubuntu 14.04 x64 installation with administrative rights. We have tested the installation guide on an @@ -144,7 +144,7 @@ with OpenProject. For more information, see https://github.com/opf/openproject-c ```bash [openproject@host] cd ~ -[openproject@host] git clone https://github.com/opf/openproject-ce.git --branch stable/6 --depth 1 +[openproject@host] git clone https://github.com/opf/openproject-ce.git --branch stable/7 --depth 1 [openproject@host] cd openproject-ce [openproject@host] gem install bundler [openproject@host] bundle install --deployment --without postgres sqlite development test therubyracer docker From 259869ab46df2ddc931172066195553f7282f3b5 Mon Sep 17 00:00:00 2001 From: Niels Lindenthal Date: Thu, 15 Jun 2017 07:59:10 +0200 Subject: [PATCH 18/29] Add note on manual installation [ci skip] --- docs/installation/manual/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/installation/manual/README.md b/docs/installation/manual/README.md index 571ce705f8..0d94dfaa80 100644 --- a/docs/installation/manual/README.md +++ b/docs/installation/manual/README.md @@ -1,5 +1,8 @@ # Manual installation of OpenProject 7.0 with Apache on Ubuntu 14.04. LTS +**IMPORTANT: We strongly recommend to use the [OpenProject installers](https://www.openproject.org/download-and-installation) (packaged installation). There is no real advantage installing OpenProject manually.** + + This tutorial helps you to deploy OpenProject 7.0. Please, aware that: This guide requires that you have a clean Ubuntu 14.04 x64 installation From 66ad85f392d0b9f5e0222fd158bbccdbb5ac7ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 15 Jun 2017 09:45:41 +0200 Subject: [PATCH 19/29] Properly parse boolean value [ci skip] --- lib/tasks/ldap.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/ldap.rake b/lib/tasks/ldap.rake index 0773e2351d..44e60eedc9 100644 --- a/lib/tasks/ldap.rake +++ b/lib/tasks/ldap.rake @@ -103,7 +103,7 @@ namespace :ldap do account: url.user, account_password: url.password, base_dn: url.dn, - onthefly_register: !!args[:onthefly], + onthefly_register: !!ActiveModel::Type::Boolean.new.cast(args[:onthefly]), attr_login: args[:map_login], attr_firstname: args[:map_firstname], attr_lastname: args[:map_lastname], From ba917c76e57ae11d16a29e32077bf95edb08a543 Mon Sep 17 00:00:00 2001 From: ulferts Date: Thu, 15 Jun 2017 14:19:58 +0200 Subject: [PATCH 20/29] limit query selection dropdown height (#5655) [ci skip] --- app/assets/stylesheets/layout/_toolbar.sass | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/stylesheets/layout/_toolbar.sass b/app/assets/stylesheets/layout/_toolbar.sass index de73746771..5c7700b494 100644 --- a/app/assets/stylesheets/layout/_toolbar.sass +++ b/app/assets/stylesheets/layout/_toolbar.sass @@ -272,6 +272,9 @@ top: 24px right: 22px color: #999999 + .ui-widget-content.-inplace + max-height: 55vh + overflow-x: scroll input[type="search"]::-webkit-search-cancel-button display: none From 877937180ed7daba7481275d2dc5a739cc82ba63 Mon Sep 17 00:00:00 2001 From: ulferts Date: Thu, 15 Jun 2017 16:06:32 +0200 Subject: [PATCH 21/29] fix bulk destroy for wps of more than one project (#5656) In the scenario of destroying work packages from multiple projects at once, @project is undefined. As such, we cannot render a project specific path. But we can simply go back in history [ci skip] --- app/views/work_packages/bulk/destroy.html.erb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/views/work_packages/bulk/destroy.html.erb b/app/views/work_packages/bulk/destroy.html.erb index 8e7873ed4e..bffc5579dd 100644 --- a/app/views/work_packages/bulk/destroy.html.erb +++ b/app/views/work_packages/bulk/destroy.html.erb @@ -81,11 +81,10 @@ See doc/COPYRIGHT.rdoc for more details. concat content_tag :i, '', class: 'button--icon icon-delete' concat content_tag :span, l(:button_delete), class: 'button--text' end %> - <%= link_to project_work_packages_path(@project), - title: l(:button_cancel), - class: 'button -with-icon icon-cancel' do %> - <%= l(:button_cancel) %> - <% end %> + <%= link_to_function l(:button_cancel), + "history.back()", + title: l(:button_cancel), + class: 'button -with-icon icon-cancel'%> <% end %> From 02e418374f90204b10ec060648e9b7f4bff6b841 Mon Sep 17 00:00:00 2001 From: ulferts Date: Fri, 16 Jun 2017 13:39:03 +0200 Subject: [PATCH 22/29] only nest error message on invalid query (#5647) [ci skip] --- .../hal-resources/error-resource.service.ts | 11 +++-- .../app/components/wp-list/wp-list.service.ts | 46 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/frontend/app/components/api/api-v3/hal-resources/error-resource.service.ts b/frontend/app/components/api/api-v3/hal-resources/error-resource.service.ts index 211a606827..cd9e7a2e53 100644 --- a/frontend/app/components/api/api-v3/hal-resources/error-resource.service.ts +++ b/frontend/app/components/api/api-v3/hal-resources/error-resource.service.ts @@ -27,7 +27,10 @@ //++ import {HalResource} from './hal-resource.service'; -import {opApiModule} from "../../../../angular-modules"; +import {opApiModule} from '../../../../angular-modules'; + +export const v3ErrorIdentifierQueryInvalid = 'urn:openproject-org:api:v3:errors:InvalidQuery'; +export const v3ErrorIdentifierMultipleErrors = 'urn:openproject-org:api:v3:errors:MultipleErrors'; export class ErrorResource extends HalResource { public errors:any[]; @@ -44,14 +47,14 @@ export class ErrorResource extends HalResource { } public isMultiErrorMessage() { - return this.errorIdentifier === 'urn:openproject-org:api:v3:errors:MultipleErrors'; + return this.errorIdentifier === v3ErrorIdentifierMultipleErrors; } public getInvolvedAttributes():string[] { var columns = []; if (this.details) { - columns = [{ details: this.details }] + columns = [{ details: this.details }]; } else if (this.errors) { columns = this.errors; @@ -60,7 +63,7 @@ export class ErrorResource extends HalResource { return columns.map(field => field.details.attribute); } - public getMessagesPerAttribute():{ [attribute:string]: string[] } { + public getMessagesPerAttribute():{ [attribute:string]:string[] } { let perAttribute:any = {}; if (this.details) { diff --git a/frontend/app/components/wp-list/wp-list.service.ts b/frontend/app/components/wp-list/wp-list.service.ts index dd3e5d5cb0..0e490195eb 100644 --- a/frontend/app/components/wp-list/wp-list.service.ts +++ b/frontend/app/components/wp-list/wp-list.service.ts @@ -32,7 +32,10 @@ import {PaginationObject, QueryDmService} from "../api/api-v3/hal-resource-dms/q import {QueryFormDmService} from "../api/api-v3/hal-resource-dms/query-form-dm.service"; import {States} from "../states.service"; import {SchemaResource} from "../api/api-v3/hal-resources/schema-resource.service"; -import {ErrorResource} from "../api/api-v3/hal-resources/error-resource.service"; +import { + ErrorResource, + v3ErrorIdentifierQueryInvalid +} from '../api/api-v3/hal-resources/error-resource.service'; import {WorkPackageCollectionResource} from "../api/api-v3/hal-resources/wp-collection-resource.service"; import {QuerySchemaResourceInterface} from "../api/api-v3/hal-resources/query-schema-resource.service"; import {QueryFilterInstanceSchemaResource} from "../api/api-v3/hal-resources/query-filter-instance-schema-resource.service"; @@ -364,30 +367,35 @@ export class WorkPackagesListService { private handleQueryLoadingError(error:ErrorResource, queryProps:any, queryId:number, projectIdentifier?:string) { let deferred = this.$q.defer(); - this.NotificationsService.addError(this.I18n.t('js.work_packages.faulty_query.description'), error.message); + if (error.errorIdentifier === v3ErrorIdentifierQueryInvalid) { + this.NotificationsService.addError(this.I18n.t('js.work_packages.faulty_query.description'), error.message); - this.QueryFormDm.loadWithParams(queryProps, queryId, projectIdentifier) - .then(form => { - this.QueryDm.findDefault({pageSize: 0}, projectIdentifier) - .then((query:QueryResource) => { - this.wpListInvalidQueryService.restoreQuery(query, form); + this.QueryFormDm.loadWithParams(queryProps, queryId, projectIdentifier) + .then(form => { + this.QueryDm.findDefault({pageSize: 0}, projectIdentifier) + .then((query:QueryResource) => { + this.wpListInvalidQueryService.restoreQuery(query, form); - query.results.pageSize = queryProps.pageSize; - query.results.total = 0; + query.results.pageSize = queryProps.pageSize; + query.results.total = 0; - if (queryId) { - query.id = queryId; - } + if (queryId) { + query.id = queryId; + } - this.states.table.context.doAndTransition('Query loaded', () => { - this.updateStatesFromQuery(query); - this.updateStatesFromForm(query, form); - }); + this.states.table.context.doAndTransition('Query loaded', () => { + this.updateStatesFromQuery(query); + this.updateStatesFromForm(query, form); + }); - deferred.resolve(query); - }); - }); + deferred.resolve(query); + }); + }); + } else { + this.NotificationsService.addError(error.message, []); + deferred.resolve(); + } return deferred.promise; } From 6e05f96cb584a74f41d96c29fb9d33c680d6dab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Fri, 16 Jun 2017 14:10:30 +0200 Subject: [PATCH 23/29] [25554] Let long-text attributes span both columns (#5658) * [25554] Let long-text attributes span both columns https://community.openproject.com/work_packages/25554 * Attempt to reconnect on pullpreview [ci skip] --- .../single_view/_single_view.sass | 19 +++++++++++++++++++ .../layout/_work_package_table.sass | 17 ----------------- docker-compose.pullpreview.yml | 2 +- .../wp-single-view.directive.html | 10 ++++++---- .../wp-single-view.directive.ts | 2 ++ .../wp-display-formattable-field.module.ts | 4 ++++ .../wp-display-field.module.ts | 4 ++++ 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass b/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass index 32a1a2788d..9315362c51 100644 --- a/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass +++ b/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass @@ -159,3 +159,22 @@ i &:before @include varprop(color, $body-font-color) + + +// Implement two column layout for WP full screen view +@media screen and (min-width: 90rem) + .action-show .attributes-group, + .full-create .attributes-group + .-columns-2 + column-count: 2 + column-gap: 4rem + + .attributes-key-value + -webkit-column-break-inside: avoid + page-break-inside: avoid + break-inside: avoid + + // Let some elements still span both columns + &.-span-all-columns + column-span: all + diff --git a/app/assets/stylesheets/layout/_work_package_table.sass b/app/assets/stylesheets/layout/_work_package_table.sass index e9ec11a544..d94950faa5 100644 --- a/app/assets/stylesheets/layout/_work_package_table.sass +++ b/app/assets/stylesheets/layout/_work_package_table.sass @@ -241,20 +241,3 @@ overflow: overlay #content overflow-y: auto - -// Implement two column layout for WP full screen view -@media screen and (min-width: 90rem) - .action-show .attributes-group, - .full-create .attributes-group - .-columns-2 - column-count: 2 - column-gap: 4rem - - .attributes-key-value - -webkit-column-break-inside: avoid - page-break-inside: avoid - break-inside: avoid - - - - diff --git a/docker-compose.pullpreview.yml b/docker-compose.pullpreview.yml index 3455b04380..1883077eb8 100644 --- a/docker-compose.pullpreview.yml +++ b/docker-compose.pullpreview.yml @@ -18,7 +18,7 @@ worker: &ruby - db environment: - "RAILS_CACHE_STORE=file_store" - - "DATABASE_URL=postgresql://app:p4ssw0rd@db:5432/app?encoding=utf8&pool=5&timeout=5000" + - "DATABASE_URL=postgresql://app:p4ssw0rd@db:5432/app?encoding=utf8&pool=5&timeout=5000&reconnect=true" - "SECRET_KEY_BASE=d4e74f017910ac56c6ebad01165b7e1b37f4c9c02e9716836f8670cdc8d65a231e64e4f6416b19c8" - "RAILS_ENV=production" - "HEROKU=true" diff --git a/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html b/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html index c29cf756a0..ae9125b746 100644 --- a/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html +++ b/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html @@ -18,7 +18,9 @@
-
+
@@ -64,9 +66,9 @@
-
+
Date: Mon, 19 Jun 2017 10:32:58 +0200 Subject: [PATCH 24/29] hide horizontal scrollbar (#5670) vertical scrollbar only displayed when required. Adjust margins [ci skip] --- app/assets/stylesheets/content/_autocomplete.sass | 2 +- app/assets/stylesheets/layout/_toolbar.sass | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/content/_autocomplete.sass b/app/assets/stylesheets/content/_autocomplete.sass index ea80dba163..5ad35343c9 100644 --- a/app/assets/stylesheets/content/_autocomplete.sass +++ b/app/assets/stylesheets/content/_autocomplete.sass @@ -88,7 +88,7 @@ div.autocomplete &.-inplace position: relative border: none - padding-top: 15px + margin-top: 15px line-height: 1.6 font-size: 1rem diff --git a/app/assets/stylesheets/layout/_toolbar.sass b/app/assets/stylesheets/layout/_toolbar.sass index 5c7700b494..fb7f52216a 100644 --- a/app/assets/stylesheets/layout/_toolbar.sass +++ b/app/assets/stylesheets/layout/_toolbar.sass @@ -248,6 +248,7 @@ display: block .search-query-wrapper padding: 15px + overflow: hidden .query-select-dropdown--no-results padding: 15px 15px 0 .ui-menu-item @@ -274,7 +275,7 @@ color: #999999 .ui-widget-content.-inplace max-height: 55vh - overflow-x: scroll + overflow-x: auto input[type="search"]::-webkit-search-cancel-button display: none From 5165906e11ba9ca53c0e9e183a9297f9bd95a7de Mon Sep 17 00:00:00 2001 From: ulferts Date: Mon, 19 Jun 2017 11:28:37 +0200 Subject: [PATCH 25/29] fix saving boolean cf filters, use representer for filter parsing (#5660) * fix saving boolean cf filters, use representer for filter parsing * patch roar to allow linked_reseource definitions This enables us to get rid of dedicated representers for links sections when the representer is used for parsing [ci skip] --- lib/api/decorators/link_object.rb | 1 + lib/api/decorators/linked_resource.rb | 88 ++++++++++++++ .../query_filter_instance_representer.rb | 110 ++++++++++++------ lib/api/v3/queries/query_serialization.rb | 22 +--- .../api/v3/queries/create_form_api_spec.rb | 15 ++- .../api/v3/queries/update_form_api_spec.rb | 17 ++- 6 files changed, 197 insertions(+), 56 deletions(-) create mode 100644 lib/api/decorators/linked_resource.rb diff --git a/lib/api/decorators/link_object.rb b/lib/api/decorators/link_object.rb index b1f113c2e6..b9737ad6a2 100644 --- a/lib/api/decorators/link_object.rb +++ b/lib/api/decorators/link_object.rb @@ -1,4 +1,5 @@ #-- encoding: UTF-8 + #-- copyright # OpenProject is a project management system. # Copyright (C) 2012-2017 the OpenProject Foundation (OPF) diff --git a/lib/api/decorators/linked_resource.rb b/lib/api/decorators/linked_resource.rb new file mode 100644 index 0000000000..9012e18d0b --- /dev/null +++ b/lib/api/decorators/linked_resource.rb @@ -0,0 +1,88 @@ +#-- encoding: UTF-8 + +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2017 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# 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. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +module API + module Decorators + module LinkedResource + def self.included(base) + base.extend ClassMethods + end + + def self.prepended(base) + base.extend ClassMethods + end + + def to_hash(*) + super.tap do |hash| + links = {} + representable_attrs.find_all do |dfn| + next unless dfn[:linked_resource] + name = dfn[:as] ? dfn[:as].(nil) : dfn.name + fragment = hash.delete(name) + next unless fragment + links[name] = fragment + end + + hash['_links'].merge!(links) + end + end + + def from_hash(hash, *) + return super unless hash['_links'] + + representable_attrs.find_all do |dfn| + next unless dfn[:linked_resource] + name = dfn[:as] ? dfn[:as].(nil) : dfn.name + fragment = hash['_links'].delete(name) + next unless fragment + + hash[name] = fragment + end + + super + end + + module ClassMethods + def linked_resource(name, + getter:, + setter:, + show_if: ->(*) { true }) + + property name, + exec_context: :decorator, + getter: getter, + setter: setter, + if: show_if, + linked_resource: true + end + end + end + end +end diff --git a/lib/api/v3/queries/filters/query_filter_instance_representer.rb b/lib/api/v3/queries/filters/query_filter_instance_representer.rb index 96831bb0ae..5bb1571870 100644 --- a/lib/api/v3/queries/filters/query_filter_instance_representer.rb +++ b/lib/api/v3/queries/filters/query_filter_instance_representer.rb @@ -33,45 +33,78 @@ module V3 module Queries module Filters class QueryFilterInstanceRepresenter < ::API::Decorators::Single + include API::Decorators::LinkedResource + def initialize(model) super(model, current_user: nil, embed_links: true) end - link :filter do - { - href: api_v3_paths.query_filter(converted_name), - title: name - } - end - - link :operator do - { - href: api_v3_paths.query_operator(CGI.escape(represented.operator)), - title: operator_name - } - end - - links :values do - next unless represented.ar_object_filter? - - represented.value_objects.map do |value_object| - { - href: api_v3_paths.send(value_object.class.name.demodulize.underscore, value_object.id), - title: value_object.name - } + def to_hash(*) + # We need to move the values property back from + # the links section. It got moved there because + # of the equally named linked_resource + super.tap do |hash| + unless represented.ar_object_filter? + hash['values'] = hash['_links'].delete('values') + end end end link :schema do + api_v3_paths.query_filter_instance_schema(converted_name) + end + + link :filter do { - href: api_v3_paths.query_filter_instance_schema(converted_name) + href: api_v3_paths.query_filter(converted_name), + title: name } end + linked_resource :operator, + getter: ->(*) { + hash = { + href: api_v3_paths.query_operator(CGI.escape(represented.operator)) + } + + hash[:title] = represented.operator_class.human_name if represented.operator_class.present? + hash + }, + setter: ->(value, **) { + next unless value + + represented.operator = ::API::Utilities::ResourceLinkParser.parse_id value["href"], + property: 'operator', + expected_version: '3', + expected_namespace: 'queries/operators' + } + + linked_resource :values, + getter: ->(*) { + represented.value_objects.map do |value_object| + { + href: api_v3_paths.send(value_object.class.name.demodulize.underscore, value_object.id), + title: value_object.name + } + end + }, + setter: ->(values, **) { + next unless values + + represented.values = values.map do |value| + ::API::Utilities::ResourceLinkParser.parse(value["href"])[:id] + end + }, + show_if: ->(*) { represented.ar_object_filter? } + property :name, - exec_context: :decorator + exec_context: :decorator, + writeable: false - property :values, + # Need to use property_values instead of values + # to prevent name clashes with the values link + property :property_values, + as: :values, if: ->(*) { !represented.ar_object_filter? }, exec_context: :decorator, show_nil: true @@ -82,7 +115,7 @@ def name represented.human_name end - def values + def property_values if represented.respond_to?(:custom_field) && represented.custom_field.field_format == 'bool' represented.values.map do |value| @@ -97,20 +130,31 @@ def values end end + def property_values=(vals) + represented.values = if represented.respond_to?(:custom_field) && + represented.custom_field.field_format == 'bool' + vals.map do |value| + if value + CustomValue::BoolStrategy::DB_VALUE_TRUE + else + CustomValue::BoolStrategy::DB_VALUE_FALSE + end + end + else + vals + end + end + def _type "#{converted_name.camelize}QueryFilter" end def converted_name - convert_attribute(represented.name) - end - - def operator_name - represented.operator_class.human_name if represented.operator_class.present? + ::API::Utilities::PropertyNameConverter.from_ar_name(represented.name) end - def convert_attribute(attribute) - ::API::Utilities::PropertyNameConverter.from_ar_name(attribute) + def query_filter_instance_links_representer(represented) + ::API::V3::Queries::Filters::QueryFilterInstanceLinksRepresenter.new represented, current_user: current_user end end end diff --git a/lib/api/v3/queries/query_serialization.rb b/lib/api/v3/queries/query_serialization.rb index 7646bdd17f..ab298ce054 100644 --- a/lib/api/v3/queries/query_serialization.rb +++ b/lib/api/v3/queries/query_serialization.rb @@ -58,10 +58,13 @@ def filters=(filters_hash) filters_hash.each do |filter_attributes| name = get_filter_name filter_attributes - operator = get_filter_operator filter_attributes - if name && operator - represented.add_filter name, operator, get_filter_values(filter_attributes) + filter = represented.filter_for name + if filter + filter_representer = ::API::V3::Queries::Filters::QueryFilterInstanceRepresenter.new(filter) + + filter = filter_representer.from_hash filter_attributes + represented.filters << filter else raise API::Errors::InvalidRequestBody, "Could not read filter from: #{filter_attributes}" end @@ -97,19 +100,6 @@ def get_filter_name(filter_attributes) ::API::Utilities::QueryFiltersNameConverter.to_ar_name id, refer_to_ids: true if id end - def get_filter_operator(filter_attributes) - op_href = filter_attributes.dig("_links", "operator", "href") - - id_from_href "queries/operators", op_href - end - - def get_filter_values(filter_attributes) - filter_attributes["values"] || - Array(filter_attributes.dig("_links", "values")) - .map { |value| id_from_href nil, value["href"] } - .compact - end - def initialize_links!(attributes) set_project_id(attributes) set_group_by(attributes) diff --git a/spec/requests/api/v3/queries/create_form_api_spec.rb b/spec/requests/api/v3/queries/create_form_api_spec.rb index d24fa68982..2a4604e4ba 100644 --- a/spec/requests/api/v3/queries/create_form_api_spec.rb +++ b/spec/requests/api/v3/queries/create_form_api_spec.rb @@ -1,4 +1,5 @@ #-- encoding: UTF-8 + #-- copyright # OpenProject is a project management system. # Copyright (C) 2012-2015 the OpenProject Foundation (OPF) @@ -181,10 +182,18 @@ filters = [ { "_links" => { - "filter" => { "href" => "/api/v3/queries/filters/status" }, - "operator" => { "href" => "/api/v3/queries/operators/%3D" }, + "filter" => { + "href" => "/api/v3/queries/filters/status" + }, + "operator" => { + "href" => "/api/v3/queries/operators/%3D", + "title" => 'is' + }, "values" => [ - { "href" => "/api/v3/statuses/#{status.id}" } + { + "href" => "/api/v3/statuses/#{status.id}", + "title" => status.name + } ] } } diff --git a/spec/requests/api/v3/queries/update_form_api_spec.rb b/spec/requests/api/v3/queries/update_form_api_spec.rb index 39c5bbda0d..0dca721c4c 100644 --- a/spec/requests/api/v3/queries/update_form_api_spec.rb +++ b/spec/requests/api/v3/queries/update_form_api_spec.rb @@ -1,4 +1,5 @@ #-- encoding: UTF-8 + #-- copyright # OpenProject is a project management system. # Copyright (C) 2012-2015 the OpenProject Foundation (OPF) @@ -35,7 +36,7 @@ let(:path) { api_v3_paths.query_form(query.id) } let(:user) { FactoryGirl.create(:admin) } let(:role) { FactoryGirl.create :existing_role, permissions: permissions } - let(:permissions) { [:view_work_packages, :manage_public_queries] } + let(:permissions) { %i(view_work_packages manage_public_queries) } let!(:project) { FactoryGirl.create(:project_with_types) } @@ -188,10 +189,18 @@ filters = [ { "_links" => { - "filter" => { "href" => "/api/v3/queries/filters/status" }, - "operator" => { "href" => "/api/v3/queries/operators/%3D" }, + "filter" => { + "href" => "/api/v3/queries/filters/status" + }, + "operator" => { + "href" => "/api/v3/queries/operators/%3D", + "title" => 'is' + }, "values" => [ - { "href" => "/api/v3/statuses/#{status.id}" } + { + "href" => "/api/v3/statuses/#{status.id}", + "title" => status.name + } ] } } From 520815956d1c43239447b11d6812b18b44c2be70 Mon Sep 17 00:00:00 2001 From: ulferts Date: Mon, 19 Jun 2017 12:55:28 +0200 Subject: [PATCH 26/29] preserve params when redirecting for login on repository (#5671) [ci skip] --- app/controllers/repositories_controller.rb | 4 +++ config/routes.rb | 3 ++- .../repositories_controller_spec.rb | 25 ++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 7f741447f8..8690a67ff6 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -489,6 +489,10 @@ def graph_commits_per_author(repository) ) graph.burn end + + def login_back_url_params + params.permit(:path) + end end class Date diff --git a/config/routes.rb b/config/routes.rb index b569e14f54..a7678b9366 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -348,7 +348,8 @@ get '(/revisions/:rev)(/*path)', action: :show, format: false, - rev: /[a-z0-9\.\-_]+/ + rev: /[a-z0-9\.\-_]+/, + as: 'show_revisions_path' end end diff --git a/spec/controllers/repositories_controller_spec.rb b/spec/controllers/repositories_controller_spec.rb index 3dbaf1c391..5f3a2ea698 100644 --- a/spec/controllers/repositories_controller_spec.rb +++ b/spec/controllers/repositories_controller_spec.rb @@ -35,10 +35,11 @@ allow(Project).to receive(:find).and_return(project) project end - let(:user) { + let(:user) do FactoryGirl.create(:user, member_in_project: project, member_through_role: role) - } + end + let(:role) { FactoryGirl.create(:role, permissions: []) } let (:url) { 'file:///tmp/something/does/not/exist.svn' } let(:repository) do @@ -167,7 +168,7 @@ end end - describe 'with filesystem repository' do + describe 'with subversion repository' do with_subversion_repository do |repo_dir| let(:root_url) { repo_dir } let(:url) { "file://#{root_url}" } @@ -332,4 +333,22 @@ end end end + + describe 'when not being logged in' do + let(:anonymous) { FactoryGirl.build_stubbed(:anonymous) } + + before do + login_as(anonymous) + end + + describe '#show' do + it 'redirects to login while preserving the path' do + params = { path: 'aDir/within/aDir', rev: '42', project_id: project.id } + get :show, params: params + + expect(response) + .to redirect_to signin_path(back_url: show_revisions_path_project_repository_url(params)) + end + end + end end From a100a13e6f384e8d7d51c3e917086a756c8114fd Mon Sep 17 00:00:00 2001 From: ulferts Date: Mon, 19 Jun 2017 16:17:25 +0200 Subject: [PATCH 27/29] deal with wildcard in http accept language header (#5674) Having a * in the HTTP_ACCEPT_LANGUAGE header is valid, but OP did not deal with it correctly. On top of that, it accepted every input from that header and turned it into a regexp. [ci skip] --- lib/redmine/i18n.rb | 1 + spec/lib/redmine/i18n_spec.rb | 6 ++++++ spec/services/set_localization_service_spec.rb | 12 ++++++++++++ 3 files changed, 19 insertions(+) diff --git a/lib/redmine/i18n.rb b/lib/redmine/i18n.rb index e24691e8f1..d1fba6987d 100644 --- a/lib/redmine/i18n.rb +++ b/lib/redmine/i18n.rb @@ -153,6 +153,7 @@ def all_languages ## # Returns the given language if it is valid or nil otherwise. def find_language(lang) + return nil unless lang =~ /[a-z-]+/i valid_languages.detect { |l| l =~ /#{lang}/i } if lang.present? end diff --git a/spec/lib/redmine/i18n_spec.rb b/spec/lib/redmine/i18n_spec.rb index fbfbd79026..6c9a3574b8 100644 --- a/spec/lib/redmine/i18n_spec.rb +++ b/spec/lib/redmine/i18n_spec.rb @@ -150,6 +150,12 @@ module OpenProject it 'can be found by uppercase if it is active' do expect(find_language(:DE)).to eql :de end + + it 'is nil if non valid string is passed' do + expect(find_language('*')).to be_nil + expect(find_language('78445')).to be_nil + expect(find_language('/)(')).to be_nil + end end describe 'link_translation' do diff --git a/spec/services/set_localization_service_spec.rb b/spec/services/set_localization_service_spec.rb index c5d5eda54b..f011d0cd24 100644 --- a/spec/services/set_localization_service_spec.rb +++ b/spec/services/set_localization_service_spec.rb @@ -106,6 +106,12 @@ def expect_locale(locale) it_behaves_like "falls back to the instane's default language" end + + context 'with wildcard header set' do + let(:http_accept_language) { '*' } + + it_behaves_like "falls back to the instane's default language" + end end end @@ -119,5 +125,11 @@ def expect_locale(locale) it_behaves_like "falls back to the instane's default language" end + + context 'with a wildcard header set' do + let(:http_accept_language) { '*' } + + it_behaves_like "falls back to the instane's default language" + end end end From 5d84add246203230361cd4055dded5d770d97da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 29 Jun 2017 08:30:40 +0200 Subject: [PATCH 28/29] Expire sessions in warden auth scope --- app/controllers/application_controller.rb | 9 +-- .../authentication/session_expiry.rb | 20 ++++++ .../strategies/warden/session.rb | 6 +- spec/features/security/session_ttl_spec.rb | 72 +++++++++++++++++++ 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 lib/open_project/authentication/session_expiry.rb create mode 100644 spec/features/security/session_ttl_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8e24f9a317..4ab1227f90 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -42,6 +42,7 @@ class ApplicationController < ActionController::Base include I18n include Redmine::I18n include HookHelper + include ::OpenProject::Authentication::SessionExpiry layout 'base' @@ -675,13 +676,7 @@ def stop_if_feeds_disabled private def session_expired? - !api_request? && current_user.logged? && - (session_ttl_enabled? && (session[:updated_at].nil? || - (session[:updated_at] + Setting.session_ttl.to_i.minutes) < Time.now)) - end - - def session_ttl_enabled? - Setting.session_ttl_enabled? && Setting.session_ttl.to_i >= 5 + !api_request? && current_user.logged? && session_ttl_expired? end def permitted_params diff --git a/lib/open_project/authentication/session_expiry.rb b/lib/open_project/authentication/session_expiry.rb new file mode 100644 index 0000000000..e985b4c69f --- /dev/null +++ b/lib/open_project/authentication/session_expiry.rb @@ -0,0 +1,20 @@ +module OpenProject + module Authentication + module SessionExpiry + def session_ttl_enabled? + Setting.session_ttl_enabled? && Setting.session_ttl.to_i >= 5 + end + + def session_ttl_minutes + Setting.session_ttl.to_i.minutes + end + + def session_ttl_expired? + # Only when the TTL setting exists + return false unless session_ttl_enabled? + + session[:updated_at].nil? || (session[:updated_at] + session_ttl_minutes) < Time.now + end + end + end +end diff --git a/lib/open_project/authentication/strategies/warden/session.rb b/lib/open_project/authentication/strategies/warden/session.rb index 9cb47db1ba..3929bf1726 100644 --- a/lib/open_project/authentication/strategies/warden/session.rb +++ b/lib/open_project/authentication/strategies/warden/session.rb @@ -1,3 +1,5 @@ +require 'open_project/authentication/session_expiry' + module OpenProject module Authentication module Strategies @@ -7,8 +9,10 @@ module Warden # not been unified in terms of Warden strategies and is only locally # applied to the API v3. class Session < ::Warden::Strategies::Base + include ::OpenProject::Authentication::SessionExpiry + def valid? - session + session && !session_ttl_expired? end def authenticate! diff --git a/spec/features/security/session_ttl_spec.rb b/spec/features/security/session_ttl_spec.rb new file mode 100644 index 0000000000..fb6f8c971d --- /dev/null +++ b/spec/features/security/session_ttl_spec.rb @@ -0,0 +1,72 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2017 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# 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. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe 'Session TTL', + with_settings: {session_ttl_enabled?: true, session_ttl: '10'}, + type: :feature do + let!(:user) {FactoryGirl.create :admin} + let!(:work_package) {FactoryGirl.create :work_package} + + before do + login_with(user.login, user.password) + end + + def expire! + page.set_rack_session(updated_at: Time.now - 1.hour) + end + + describe 'outdated TTL on Rails request' do + it 'expires on the next Rails request' do + visit '/my/account' + expect(page).to have_selector('.form--field-container', text: user.login) + + # Expire the session + expire! + + visit '/' + expect(page).to have_selector('.action-login') + end + end + + describe 'outdated TTL on API request' do + it 'expires on the next APIv3 request' do + visit "/api/v3/work_packages/#{work_package.id}" + + body = JSON.parse(page.body) + expect(body['id']).to eq(work_package.id) + + # Expire the session + expire! + visit "/api/v3/work_packages/#{work_package.id}" + + expect(page.body).to eq('unauthorized') + end + end +end From 100efa6006b085976618b0b3c650b4325a080ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 29 Jun 2017 13:11:39 +0200 Subject: [PATCH 29/29] Release opf/openproject --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4d9b282569..1b6b252152 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,8 +68,8 @@ GIT GIT remote: https://github.com/opf/openproject-translations.git - revision: 5ce6b92a2e184f521fba05b8db1aabf2b61a553d - branch: release/7.0 + revision: 04af925b27f647bb45c23244d5d40e5f27d81761 + branch: stable/7 specs: openproject-translations (7.0.3) crowdin-api (~> 0.4.1)