Disable placeholder on enterprise

This commit is contained in:
Oliver Günther
2025-10-15 10:40:21 +02:00
parent 3cd7157404
commit 9c51ea8e57
6 changed files with 293 additions and 21 deletions
@@ -93,7 +93,7 @@
classes: class_names("op-enterprise-banner--close-icon", classes),
scheme: :invisible,
tag: :a,
href: dismiss_enterprise_banner_path(feature_key: @dismiss_key),
href: dismiss_enterprise_banner_path(feature_key: @feature_key, dismiss_key: @dismiss_key),
data: { turbo_stream: true, turbo_method: :post },
icon: :x,
aria: { label: t("ee.upsell.hide_banner") }
@@ -63,10 +63,8 @@ class My::EnterpriseBannersController < ApplicationController
private
def get_feature_key
raw_key = params[:feature_key]
@dismiss_key = raw_key
@feature_key = raw_key.gsub(/_trial$/, "").to_sym
@feature_key = params[:feature_key].to_sym
@dismiss_key = params[:dismiss_key].presence&.to_sym || @feature_key
render_400 unless OpenProject::Token.lowest_plan_for(@feature_key)
end
+28 -12
View File
@@ -57,18 +57,34 @@ module Users::Invitation::ProjectStep
name: :principal_type,
visually_hide_label: true
) do |radio_group|
radio_group.radio_button(value: "User",
checked: model.principal_type.nil? || model.principal_type == "User",
label: User.model_name.human,
caption: I18n.t("users.invite_user_modal.type.user.description"))
radio_group.radio_button(value: "Group",
checked: model.principal_type == "Group",
label: Group.model_name.human,
caption: I18n.t("users.invite_user_modal.type.group.description"))
radio_group.radio_button(value: "PlaceholderUser",
checked: model.principal_type == "PlaceholderUser",
label: PlaceholderUser.model_name.human,
caption: I18n.t("users.invite_user_modal.type.placeholder_user.description"))
radio_group.radio_button(
value: "User",
checked: model.principal_type.nil? || model.principal_type == "User",
label: User.model_name.human,
caption: I18n.t("users.invite_user_modal.type.user.description")
)
radio_group.radio_button(
value: "Group",
checked: model.principal_type == "Group",
label: Group.model_name.human,
caption: I18n.t("users.invite_user_modal.type.group.description")
)
radio_group.radio_button(
value: "PlaceholderUser",
disabled: !EnterpriseToken.allows_to?(:placeholder_users),
checked: model.principal_type == "PlaceholderUser",
label: PlaceholderUser.model_name.human,
caption: I18n.t("users.invite_user_modal.type.placeholder_user.description")
)
end
unless EnterpriseToken.allows_to?(:placeholder_users)
f.html_content do
render(EnterpriseEdition::BannerComponent.new(:placeholder_users,
dismissable: true,
dismiss_key: "invitation_placeholder_users"))
end
end
end
end
+11 -1
View File
@@ -40,11 +40,21 @@ module Users::Invitation
attribute :message, :text, default: nil
validates :project_id, presence: true, on: :project_step
validates :principal_type, inclusion: { in: %w[User PlaceholderUser Group] }, on: :project_step
validates :principal_type,
inclusion: { in: ->(*) { available_principal_types } },
on: :project_step
validates :id_or_email, presence: true, on: :principal_step
validates :role_id, presence: true, on: :principal_step
def self.available_principal_types
if EnterpriseToken.allows_to?(:placeholder_users)
%w[User PlaceholderUser Group]
else
%w[User Group]
end
end
def project_name
project&.name || project_id
end
+1 -3
View File
@@ -379,7 +379,7 @@ en:
danger_dialog:
confirmation_live_message_checked: "The button to proceed is now active."
confirmation_live_message_unchecked: "The button to proceed is now inactive. You need to tick the checkbox to continue."
confirmation_live_message_unchecked: "The button to proceed is now inactive. You need to tick the checkbox to continue."
op_dry_validation:
or: "or"
@@ -733,8 +733,6 @@ en:
title: "Add placeholder user to %{project_name}"
title_no_ee: "Placeholder user (Enterprise edition only add-on)"
description: "Has no access to the project and no emails are sent out."
description_no_ee: 'Has no access to the project and no emails are sent out.
<br>Check out the <a href="%{eeHref}" target="_blank">Enterprise edition</a>'
already_member_message: "Already a member of %{project}"
principal:
@@ -0,0 +1,250 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# 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-2013 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 COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
RSpec.describe Users::Invitation::FormModel do
subject(:form_model) { described_class.new }
let(:project) { build_stubbed(:project) }
describe "validations" do
describe "principal_type" do
context "with enterprise token allowing placeholder users" do
before do
allow(EnterpriseToken)
.to receive(:allows_to?)
.with(:placeholder_users)
.and_return(true)
end
context "when validating on project_step" do
it "accepts User as principal_type" do
form_model.project = project
form_model.principal_type = "User"
expect(form_model).to be_valid(:project_step)
end
it "accepts PlaceholderUser as principal_type" do
form_model.project = project
form_model.principal_type = "PlaceholderUser"
expect(form_model).to be_valid(:project_step)
end
it "accepts Group as principal_type" do
form_model.project = project
form_model.principal_type = "Group"
expect(form_model).to be_valid(:project_step)
end
it "rejects invalid principal_type" do
form_model.project = project
form_model.principal_type = "InvalidType"
expect(form_model).not_to be_valid(:project_step)
expect(form_model.errors[:principal_type]).to be_present
end
it "rejects nil principal_type" do
form_model.project = project
form_model.principal_type = nil
expect(form_model).not_to be_valid(:project_step)
expect(form_model.errors[:principal_type]).to be_present
end
end
end
context "without enterprise token allowing placeholder users" do
before do
allow(EnterpriseToken)
.to receive(:allows_to?)
.with(:placeholder_users)
.and_return(false)
end
context "when validating on project_step" do
it "accepts User as principal_type" do
form_model.project = project
form_model.principal_type = "User"
expect(form_model).to be_valid(:project_step)
end
it "accepts Group as principal_type" do
form_model.project = project
form_model.principal_type = "Group"
expect(form_model).to be_valid(:project_step)
end
it "rejects PlaceholderUser as principal_type" do
form_model.project = project
form_model.principal_type = "PlaceholderUser"
expect(form_model).not_to be_valid(:project_step)
expect(form_model.errors[:principal_type]).to be_present
end
it "rejects invalid principal_type" do
form_model.project = project
form_model.principal_type = "InvalidType"
expect(form_model).not_to be_valid(:project_step)
expect(form_model.errors[:principal_type]).to be_present
end
it "rejects nil principal_type" do
form_model.project = project
form_model.principal_type = nil
expect(form_model).not_to be_valid(:project_step)
expect(form_model.errors[:principal_type]).to be_present
end
end
end
end
describe "project_id" do
context "when validating on project_step" do
it "requires project_id to be present" do
form_model.principal_type = "User"
expect(form_model).not_to be_valid(:project_step)
expect(form_model.errors[:project_id]).to be_present
end
it "is valid when project_id is present" do
form_model.project = project
form_model.principal_type = "User"
expect(form_model).to be_valid(:project_step)
end
end
end
describe "id_or_email" do
context "when validating on principal_step" do
it "requires id_or_email to be present" do
form_model.role_id = 1
expect(form_model).not_to be_valid(:principal_step)
expect(form_model.errors[:id_or_email]).to be_present
end
it "is valid when id_or_email is present" do
form_model.id_or_email = "user@example.com"
form_model.role_id = 1
expect(form_model).to be_valid(:principal_step)
end
end
end
describe "role_id" do
context "when validating on principal_step" do
it "requires role_id to be present" do
form_model.id_or_email = "user@example.com"
expect(form_model).not_to be_valid(:principal_step)
expect(form_model.errors[:role_id]).to be_present
end
it "is valid when role_id is present" do
form_model.id_or_email = "user@example.com"
form_model.role_id = 1
expect(form_model).to be_valid(:principal_step)
end
end
end
end
describe ".available_principal_types" do
context "with enterprise token allowing placeholder users" do
before do
allow(EnterpriseToken)
.to receive(:allows_to?)
.with(:placeholder_users)
.and_return(true)
end
it "returns User, PlaceholderUser, and Group" do
expect(described_class.available_principal_types).to eq(%w[User PlaceholderUser Group])
end
end
context "without enterprise token allowing placeholder users" do
before do
allow(EnterpriseToken)
.to receive(:allows_to?)
.with(:placeholder_users)
.and_return(false)
end
it "returns User and Group" do
expect(described_class.available_principal_types).to eq(%w[User Group])
end
end
end
describe "#project_name" do
it "returns the project name when project is present" do
form_model.project = project
expect(form_model.project_name).to eq(project.name)
end
it "returns the project_id when project is not present" do
form_model.project_id = 123
expect(form_model.project_name).to eq(123)
end
end
describe "#to_h" do
it "returns a hash with all attributes" do
form_model.project_id = 1
form_model.role_id = 2
form_model.principal_type = "User"
form_model.id_or_email = "user@example.com"
form_model.message = "Welcome!"
expect(form_model.to_h).to eq({
project_id: 1,
role_id: 2,
principal_type: "User",
id_or_email: "user@example.com",
message: "Welcome!"
})
end
end
end