Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions app/components/projects/index_sub_header_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,8 @@ def new_workspace_label(type)

def allowed_new_workspace_types
@allowed_new_workspace_types ||= [].tap do |types|
if OpenProject::FeatureDecisions.portfolio_models_active?
types << "portfolio" if @current_user.allowed_globally?(:add_portfolios)
types << "program" if @current_user.allowed_globally?(:add_programs)
end
types << "portfolio" if @current_user.allowed_globally?(:add_portfolios)
types << "program" if @current_user.allowed_globally?(:add_programs)
types << "project" if @current_user.allowed_globally?(:add_project)
end
end
Expand Down
1 change: 0 additions & 1 deletion app/components/projects/row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ def name_link_section
end

def workspace_type_badge
return unless OpenProject::FeatureDecisions.portfolio_models_active?
# Only show icon and type for non-project workspaces
return unless project.workspace_type.in?(["portfolio", "program"])

Expand Down
5 changes: 0 additions & 5 deletions app/controllers/portfolios/menus_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ module Portfolios
class MenusController < ApplicationController
authorization_checked! :show

before_action :not_authorized_on_feature_flag_inactive
before_action :authorize_portfolio_access, only: %i[show]

def show
Expand All @@ -47,9 +46,5 @@ def authorize_portfolio_access
render_403 unless User.current.allowed_globally?(:add_portfolios) ||
Project.portfolio.allowed_to(User.current, :view_project).any?
end

def not_authorized_on_feature_flag_inactive
render_403 unless OpenProject::FeatureDecisions.portfolio_models_active?
end
end
end
1 change: 0 additions & 1 deletion app/controllers/portfolios_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
# projects in these cases.
class PortfoliosController < ProjectsController
before_action :authorize_portfolio_access, only: %i[index]
before_action :not_authorized_on_feature_flag_inactive

skip_before_action :load_query_or_deny_access # skip using the superclass's before action because the next must be called first
before_action :set_default_query, only: %i[index] # Must be called before `load_query_or_deny_access`
Expand Down
1 change: 0 additions & 1 deletion app/controllers/programs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@
# ++

class ProgramsController < ProjectsController
before_action :not_authorized_on_feature_flag_inactive
end
4 changes: 0 additions & 4 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,6 @@ def supported_export_formats
::Exports::Register.list_formats(Project).map(&:to_s)
end

def not_authorized_on_feature_flag_inactive
render_403 unless OpenProject::FeatureDecisions.portfolio_models_active?
end

def layout_for_new
if portfolio_management_feature_missing?
"global"
Expand Down
4 changes: 0 additions & 4 deletions config/initializers/feature_decisions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@
description: "Allow exporting a meeting with FITKO styling. " \
"See #65124 for details."

OpenProject::FeatureDecisions.add :portfolio_models,
description: "Enables the creation and management of portfolio and program work spaces.",
force_active: true

OpenProject::FeatureDecisions.add :user_working_times,
description: "Enables tracking of user working hours and non-working days."

Expand Down
6 changes: 2 additions & 4 deletions config/initializers/menus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@
caption: I18n.t("label_portfolio_plural"),
icon: "briefcase",
if: ->(_) {
OpenProject::FeatureDecisions.portfolio_models_active? &&
(User.current.logged? || !Setting.login_required?) &&
(User.current.logged? || !Setting.login_required?) &&
(User.current.allowed_globally?(:add_portfolios) ||
Project.portfolio.allowed_to(User.current, :view_project).any?)
},
Expand Down Expand Up @@ -198,8 +197,7 @@
icon: "briefcase",
after: :my_page,
if: ->(_) {
OpenProject::FeatureDecisions.portfolio_models_active? &&
(User.current.logged? || !Setting.login_required?) &&
(User.current.logged? || !Setting.login_required?) &&
(User.current.allowed_globally?(:add_portfolios) ||
Project.portfolio.allowed_to(User.current, :view_project).any?)
},
Expand Down
2 changes: 0 additions & 2 deletions config/initializers/permissions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@
{ portfolios: %i[new create] },
permissible_on: :global,
require: :loggedin,
visible: -> { OpenProject::FeatureDecisions.portfolio_models_active? },
contract_actions: { portfolios: %i[create] }

map.permission :add_programs,
{ programs: %i[new create] },
permissible_on: :global,
require: :loggedin,
visible: -> { OpenProject::FeatureDecisions.portfolio_models_active? },
contract_actions: { programs: %i[create] }

map.permission :archive_project,
Expand Down
4 changes: 0 additions & 4 deletions lib/api/v3/portfolios/portfolios_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ module V3
module Portfolios
class PortfoliosAPI < ::API::OpenProjectAPI
resources :portfolios do
after_validation do
guard_feature_flag :portfolio_models
end

get &::API::V3::Utilities::Endpoints::SqlFallbackedIndex.new(model: Project,
scope: -> {
Project
Expand Down
4 changes: 0 additions & 4 deletions lib/api/v3/programs/programs_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ module V3
module Programs
class ProgramsAPI < ::API::OpenProjectAPI
resources :programs do
after_validation do
guard_feature_flag :portfolio_models
end

get &::API::V3::Utilities::Endpoints::SqlFallbackedIndex.new(model: Project,
scope: -> {
Project
Expand Down
62 changes: 18 additions & 44 deletions spec/components/projects/index_sub_header_component_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,36 +112,24 @@ def self.workspace_types = %i[portfolio program project]
context "when user has add_portfolios permission" do
let(:global_permissions) { %i[add_portfolios] }

context "without feature flag", with_flag: { portfolio_models: false } do
include_examples "renders no buttons"
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add button directly", :portfolio, upsell: true
end

context "with feature flag", with_flag: { portfolio_models: true } do
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add button directly", :portfolio, upsell: true
end

context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add button directly", :portfolio, upsell: false
end
context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add button directly", :portfolio, upsell: false
end
end

context "when user has add_programs permission" do
let(:global_permissions) { %i[add_programs] }

context "without feature flag", with_flag: { portfolio_models: false } do
include_examples "renders no buttons"
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add button directly", :program, upsell: true
end

context "with feature flag", with_flag: { portfolio_models: true } do
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add button directly", :program, upsell: true
end

context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add button directly", :program, upsell: false
end
context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add button directly", :program, upsell: false
end
end

Expand All @@ -150,46 +138,32 @@ def self.workspace_types = %i[portfolio program project]

include_examples "renders add button directly", :project, upsell: false

context "with feature flag", with_flag: { portfolio_models: true } do
context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add button directly", :project, upsell: false
end
context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add button directly", :project, upsell: false
end
end

context "when user has only part (add_project and add_programs) of permissions" do
let(:global_permissions) { %i[add_project add_programs] }

context "without feature flag", with_flag: { portfolio_models: false } do
include_examples "renders add button directly", :project, upsell: false
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add buttons in a pulldown", %i[program project], upsell: %i[program]
end

context "with feature flag", with_flag: { portfolio_models: true } do
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add buttons in a pulldown", %i[program project], upsell: %i[program]
end

context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add buttons in a pulldown", %i[program project], upsell: []
end
context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add buttons in a pulldown", %i[program project], upsell: []
end
end

context "when user has all permissions" do
let(:global_permissions) { %i[add_project add_portfolios add_programs] }

context "without feature flag", with_flag: { portfolio_models: false } do
include_examples "renders add button directly", :project, upsell: false
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add buttons in a pulldown", workspace_types, upsell: %i[portfolio program]
end

context "with feature flag", with_flag: { portfolio_models: true } do
context "without enterprise feature enabled", with_ee: [] do
include_examples "renders add buttons in a pulldown", workspace_types, upsell: %i[portfolio program]
end

context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add buttons in a pulldown", workspace_types, upsell: []
end
context "with enterprise feature enabled", with_ee: :portfolio_management do
include_examples "renders add buttons in a pulldown", workspace_types, upsell: []
end
end
end
Expand Down
88 changes: 31 additions & 57 deletions spec/controllers/portfolios_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

require "spec_helper"

RSpec.describe PortfoliosController, with_flag: { portfolio_models: true } do
RSpec.describe PortfoliosController do
shared_let(:admin) { create(:admin) }
shared_let(:restricted_user) { create(:user) }

Expand Down Expand Up @@ -92,41 +92,21 @@
let(:parent) { nil }

context "as an admin" do
context "with flag enabled", with_flag: { portfolio_models: true } do
it_behaves_like "successful request"
end

context "with flag disabled", with_flag: { portfolio_models: false } do
it "returns 403 Not Authorized" do
expect(response).not_to be_successful
expect(response).to have_http_status :forbidden
end
end
it_behaves_like "successful request"
end

context "as a non-admin with global add_portfolios permission" do
let(:user) { create(:user, global_permissions: [:add_portfolios]) }

context "with flag enabled", with_flag: { portfolio_models: true } do
it_behaves_like "successful request"
end

context "with flag disabled", with_flag: { portfolio_models: false } do
it "returns 403 Not Authorized" do
expect(response).not_to be_successful
expect(response).to have_http_status :forbidden
end
end
it_behaves_like "successful request"
end

context "as a non-admin without add_portfolios permission" do
let(:user) { create(:user) }

context "with flag enabled", with_flag: { portfolio_models: true } do
it "returns 403 Not Authorized" do
expect(response).not_to be_successful
expect(response).to have_http_status :forbidden
end
it "returns 403 Not Authorized" do
expect(response).not_to be_successful
expect(response).to have_http_status :forbidden
end
end

Expand Down Expand Up @@ -172,49 +152,43 @@
end
end

context "without the portfolio feature flag set", with_flag: { portfolio_models: false } do
it_behaves_like "forbidden index request"
end
it_behaves_like "successful index"

context "with the portfolio feature flag set" do
it_behaves_like "successful index"
it "includes active portfolios in the result" do
query = assigns(:query)
expect(query).to be_a_new(ProjectQuery)
expect(query).to be_valid

it "includes active portfolios in the result" do
query = assigns(:query)
expect(query).to be_a_new(ProjectQuery)
expect(query).to be_valid
expect(query.results.portfolio).to eq([portfolio_a, portfolio_b, portfolio_c])
end

expect(query.results.portfolio).to eq([portfolio_a, portfolio_b, portfolio_c])
end
context "with a user who does not have permission to see the portfolio module" do
let(:user) { restricted_user }

context "with a user who does not have permission to see the portfolio module" do
let(:user) { restricted_user }
it_behaves_like "forbidden index request"
end

it_behaves_like "forbidden index request"
end
context "with a user who has permission to see the portfolio module" do
context "when the user has the global add_portfolios permission" do
let(:user) { create(:user, global_permissions: [:add_portfolios]) }

context "with a user who has permission to see the portfolio module" do
context "when the user has the global add_portfolios permission" do
let(:user) { create(:user, global_permissions: [:add_portfolios]) }
it_behaves_like "successful index"
end

it_behaves_like "successful index"
context "when the user has a view_project permission on an active portfolio" do
let(:user) do
create(:user, member_with_permissions: { portfolio_a => [:view_project] })
end

context "when the user has a view_project permission on an active portfolio" do
let(:user) do
create(:user, member_with_permissions: { portfolio_a => [:view_project] })
end
it_behaves_like "successful index"
end

it_behaves_like "successful index"
context "when the user has a view_project permission on an inactive portfolio" do
let(:user) do
create(:user, member_with_permissions: { portfolio_d => [:view_project] })
end

context "when the user has a view_project permission on an inactive portfolio" do
let(:user) do
create(:user, member_with_permissions: { portfolio_d => [:view_project] })
end

it_behaves_like "forbidden index request"
end
it_behaves_like "forbidden index request"
end
end
end
Expand Down
Loading
Loading