diff --git a/db/migrate/20250721111034_add_highest_access_level_to_seat_assignments.rb b/db/migrate/20250721111034_add_highest_access_level_to_seat_assignments.rb new file mode 100644 index 0000000000000000000000000000000000000000..14d2b087ecb7d31ef3da3006d5e3cffc17c5dd49 --- /dev/null +++ b/db/migrate/20250721111034_add_highest_access_level_to_seat_assignments.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddHighestAccessLevelToSeatAssignments < Gitlab::Database::Migration[2.3] + milestone '18.3' + + def change + add_column :subscription_seat_assignments, :highest_access_level, :integer + end +end diff --git a/db/schema_migrations/20250721111034 b/db/schema_migrations/20250721111034 new file mode 100644 index 0000000000000000000000000000000000000000..2db2bb9d4873e839bf2836c6cadae81e85dd1253 --- /dev/null +++ b/db/schema_migrations/20250721111034 @@ -0,0 +1 @@ +2195f874da176acf513bcb52aa7a73c22e37d37364db8130073bd32ad57eb367 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 9fbf0a27e071ceab799c47eae7e9c57205718a75..aa498d58a24a7fb37f7c916f9833473dfa956843 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -24028,7 +24028,8 @@ CREATE TABLE subscription_seat_assignments ( created_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL, organization_id bigint NOT NULL, - seat_type smallint + seat_type smallint, + highest_access_level integer ); CREATE SEQUENCE subscription_seat_assignments_id_seq diff --git a/ee/app/services/gitlab_subscriptions/members/added_service.rb b/ee/app/services/gitlab_subscriptions/members/added_service.rb index 1659e5c54b70e4e37740f3178c1b528c3fe3ecbd..0bce23b6e67204858ed54df99724c59e7931cea3 100644 --- a/ee/app/services/gitlab_subscriptions/members/added_service.rb +++ b/ee/app/services/gitlab_subscriptions/members/added_service.rb @@ -16,16 +16,20 @@ def execute namespace_id = source.root_ancestor.id organization_id = source.root_ancestor.organization_id - recently_added_members_user_ids.each_slice(BATCH_SIZE) do |batch| - seat_assignments = batch.map do |user_id| + recently_added_members_users.each_batch(of: BATCH_SIZE) do |batch| + seat_assignments = batch.map do |group_member| + user = group_member.user + highest_access_level = user.current_highest_access_level + { + highest_access_level: highest_access_level, namespace_id: namespace_id, - user_id: user_id, - organization_id: organization_id + organization_id: organization_id, + user_id: user.id } end - GitlabSubscriptions::SeatAssignment.insert_all( + GitlabSubscriptions::SeatAssignment.upsert_all( seat_assignments, unique_by: [:namespace_id, :user_id] ) @@ -38,8 +42,8 @@ def execute attr_reader :source, :invited_user_ids - def recently_added_members_user_ids - source.members.connected_to_user.including_user_ids(invited_user_ids).pluck_user_ids + def recently_added_members_users + source.members.connected_to_user.including_user_ids(invited_user_ids).including_user end end end diff --git a/ee/spec/services/gitlab_subscriptions/members/added_service_spec.rb b/ee/spec/services/gitlab_subscriptions/members/added_service_spec.rb index 7876eaedfdab90b0ab0777c05e1f6b94ef415df6..954a4f2fc420b48d8a064deeb6d02c203a92fc24 100644 --- a/ee/spec/services/gitlab_subscriptions/members/added_service_spec.rb +++ b/ee/spec/services/gitlab_subscriptions/members/added_service_spec.rb @@ -15,29 +15,54 @@ describe 'with valid params' do let(:source) { create(:group, parent: namespace) } - it 'create a new seat assignment record' do + before do source.add_developer(user) + end + it 'create a new seat assignment record' do expect do expect(execute).to be_success end.to change { GitlabSubscriptions::SeatAssignment.where(user: user, namespace: namespace).count } .by(1) end - it 'does not create new seat_assignment record, if one already exists' do - create(:gitlab_subscription_seat_assignment, namespace: namespace, user: user) + it "saves user's highest access level" do + create(:group, parent: namespace).add_maintainer(user) - expect do - expect(execute).to be_success - end.not_to change { GitlabSubscriptions::SeatAssignment.count } + execute + + expect(GitlabSubscriptions::SeatAssignment.last.highest_access_level).to eq Gitlab::Access::MAINTAINER + end + + context 'with existing seat assignment record' do + before do + create( + :gitlab_subscription_seat_assignment, + namespace: namespace, + user: user, + highest_access_level: Gitlab::Access::DEVELOPER + ) + end + + it 'does not create new seat_assignment record' do + expect do + expect(execute).to be_success + end.not_to change { GitlabSubscriptions::SeatAssignment.count } + end + + it 'updates seat assigment record' do + create(:group, parent: namespace).add_maintainer(user) + + expect { execute } + .to change { GitlabSubscriptions::SeatAssignment.last.highest_access_level } + .from(Gitlab::Access::DEVELOPER).to(Gitlab::Access::MAINTAINER) + end end context "when source is of type 'Project'" do let(:source) { build(:project, namespace: namespace) } it 'creates new seat assignment record' do - source.add_developer(user) - expect do expect(execute).to be_success end.to change { GitlabSubscriptions::SeatAssignment.where(user: user, namespace: namespace).count }.by(1)