diff --git a/ee/app/policies/ee/global_policy.rb b/ee/app/policies/ee/global_policy.rb index 186d8a42445f88e93d3f8928e20c5f0eaf20c4ba..e733562f176125ae3fcd19b2d605a5e52bfed3a4 100644 --- a/ee/app/policies/ee/global_policy.rb +++ b/ee/app/policies/ee/global_policy.rb @@ -232,10 +232,7 @@ def duo_chat_free_access_was_cut_off? end def duo_chat_free_access_was_cut_off_for_gitlab_com? - duo_chat_free_cutoff = Time.utc(2024, 10, 17) - free_access_expired = Time.now.utc >= duo_chat_free_cutoff - - free_access_expired || user.belongs_to_group_requires_licensed_seat_for_chat? + !duo_chat.free_access? || user.belongs_to_group_requires_licensed_seat_for_chat? end def duo_chat_free_access_was_cut_off_for_sm? diff --git a/ee/config/cloud_connector/access_data.yml b/ee/config/cloud_connector/access_data.yml index 63526b3fdb5b4703dd88bef9a8b82f4bd93c4a84..736d95694936da11759ab041ebb5e1eff21d33f8 100644 --- a/ee/config/cloud_connector/access_data.yml +++ b/ee/config/cloud_connector/access_data.yml @@ -27,6 +27,8 @@ services: # Cloud connector features (i.e. code_suggestions, duo_chat...) - code_suggestions duo_chat: backend: 'gitlab-ai-gateway' + # Represents the cut-off date when the service requires addon seat purchase. + cut_off_date: 2024-10-17 00:00:00 UTC bundled_with: duo_pro: unit_primitives: diff --git a/ee/spec/lib/cloud_connector/self_signed/access_data_reader_spec.rb b/ee/spec/lib/cloud_connector/self_signed/access_data_reader_spec.rb index d31c6ee1f207554ed3638169f8513c79b6954306..53a9980454817142f40af8bbc354b61e48c07a30 100644 --- a/ee/spec/lib/cloud_connector/self_signed/access_data_reader_spec.rb +++ b/ee/spec/lib/cloud_connector/self_signed/access_data_reader_spec.rb @@ -19,6 +19,7 @@ let_it_be(:sast_backend) { 'gitlab-security-gateway' } let_it_be(:self_hosted_models_cut_off_date) { Time.zone.parse("2024-10-17 00:00:00 UTC").utc } + let_it_be(:duo_chat_cutoff_date) { Time.zone.parse("2024-10-17 00:00:00 UTC").utc } let_it_be(:self_hosted_models_bundled_with) { { "duo_enterprise" => [:code_suggestions, :duo_chat] } } let_it_be(:anthropic_proxy_bundled_with) do @@ -133,7 +134,7 @@ let_it_be(:arguments_map) do { code_suggestions: [cs_cut_off_date, cs_bundled_with, backend], - duo_chat: [nil, duo_chat_bundled_with, backend], + duo_chat: [duo_chat_cutoff_date, duo_chat_bundled_with, backend], anthropic_proxy: [nil, anthropic_proxy_bundled_with, backend], vertex_ai_proxy: [nil, vertex_ai_proxy_bundled_with, backend], resolve_vulnerability: [nil, resolve_vulnerability_bundled_with, backend], diff --git a/ee/spec/policies/global_policy_spec.rb b/ee/spec/policies/global_policy_spec.rb index adde22984f2e5ae422a595566f00c0ce44f0db6f..7a79468a09d02b2294e482bad464a3bfa8639b14 100644 --- a/ee/spec/policies/global_policy_spec.rb +++ b/ee/spec/policies/global_policy_spec.rb @@ -641,26 +641,20 @@ describe 'access_duo_chat' do let(:policy) { :access_duo_chat } - let_it_be(:before_cutoff) { Date.new(2024, 10, 16) } - let_it_be(:after_cutoff) { Date.new(2024, 10, 18) } let_it_be_with_reload(:current_user) { create(:user) } context 'when on .org or .com', :saas do where(:group_with_ai_membership, :duo_pro_seat_assigned, :requires_licensed_seat, - :frozen_date, :duo_chat_enabled_for_user) do - false | false | false | ref(:before_cutoff) | be_disallowed(policy) - false | true | false | ref(:before_cutoff) | be_disallowed(policy) - true | false | false | ref(:before_cutoff) | be_allowed(policy) - true | true | false | ref(:before_cutoff) | be_allowed(policy) - - # When Group actor belongs to a group which requires licensed seat for chat - true | false | true | ref(:before_cutoff) | be_disallowed(policy) - true | true | true | ref(:before_cutoff) | be_allowed(policy) - - # After free access cutoff - false | true | false | ref(:after_cutoff) | be_allowed(policy) - true | false | false | ref(:after_cutoff) | be_disallowed(policy) + :free_access, :duo_chat_enabled_for_user) do + false | false | false | true | be_disallowed(policy) + false | true | false | true | be_disallowed(policy) + true | false | false | true | be_allowed(policy) + true | true | false | true | be_allowed(policy) + true | false | true | true | be_disallowed(policy) + true | true | true | true | be_allowed(policy) + false | true | false | false | be_allowed(policy) + true | false | false | false | be_disallowed(policy) end with_them do @@ -670,9 +664,9 @@ allow(CloudConnector::AvailableServices).to receive(:find_by_name).with(:duo_chat) .and_return(duo_chat_service_data) allow(duo_chat_service_data).to receive(:allowed_for?).with(current_user).and_return(duo_pro_seat_assigned) + allow(duo_chat_service_data).to receive(:free_access?).and_return(free_access) allow(current_user).to receive(:belongs_to_group_requires_licensed_seat_for_chat?) .and_return(requires_licensed_seat) - travel_to(frozen_date) end it { is_expected.to duo_chat_enabled_for_user } @@ -719,13 +713,16 @@ context 'when duo chat is self hosted' do where(:duo_chat_on_saas, :ai_chat_available, :self_hosted, :allowed_to_use, - :free, :beta_ended, :duo_chat_enabled_for_user) do - true | true | true | true | true | true | be_allowed(policy) - false | false | true | true | true | true | be_disallowed(policy) - false | true | true | true | true | true | be_allowed(policy) - true | true | false | true | true | true | be_disallowed(policy) - true | true | true | false | true | false | be_allowed(policy) - true | true | true | false | true | true | be_disallowed(policy) + :free, :beta_ended, :duo_chat_free, :duo_chat_enabled_for_user) do + true | true | true | true | true | true | true | be_allowed(policy) + false | false | true | true | true | true | true | be_disallowed(policy) + false | true | true | true | true | true | true | be_allowed(policy) + true | true | false | true | true | true | true | be_disallowed(policy) + true | true | true | false | true | false | true | be_allowed(policy) + true | true | true | false | true | true | true | be_disallowed(policy) + true | true | true | true | true | true | false | be_allowed(policy) + true | true | true | true | true | false | true | be_allowed(policy) + true | true | true | true | false | true | true | be_allowed(policy) end with_them do @@ -738,10 +735,14 @@ :self_hosted?).and_return(self_hosted) self_hosted_service_data = instance_double(CloudConnector::SelfSigned::AvailableServiceData) + duo_chat_service_data = instance_double(CloudConnector::SelfSigned::AvailableServiceData) allow(CloudConnector::AvailableServices).to receive(:find_by_name).with(:self_hosted_models) .and_return(self_hosted_service_data) + allow(CloudConnector::AvailableServices).to receive(:find_by_name).with(:duo_chat) + .and_return(duo_chat_service_data) allow(self_hosted_service_data).to receive(:allowed_for?).with(current_user).and_return(allowed_to_use) allow(self_hosted_service_data).to receive(:free_access?).and_return(free) + allow(duo_chat_service_data).to receive(:free_access?).and_return(duo_chat_free) end it { is_expected.to duo_chat_enabled_for_user }