diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-02 12:09:15 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-02 12:09:15 +0000 |
commit | d10ab00450821139b9b933269454e42ce6e16798 (patch) | |
tree | 199046376ee4cc236c1166e47c2271136f0f8427 /app/services/authorized_project_update | |
parent | afcacea9362b7990b80696c2e63c2a9100f92ab5 (diff) | |
download | gitlab-ce-d10ab00450821139b9b933269454e42ce6e16798.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/authorized_project_update')
-rw-r--r-- | app/services/authorized_project_update/find_records_due_for_refresh_service.rb | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/app/services/authorized_project_update/find_records_due_for_refresh_service.rb b/app/services/authorized_project_update/find_records_due_for_refresh_service.rb new file mode 100644 index 00000000000..d6de10fb8aa --- /dev/null +++ b/app/services/authorized_project_update/find_records_due_for_refresh_service.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +module AuthorizedProjectUpdate + # Service for finding the authorized_projects records of a user that needs addition or removal. + # + # Usage: + # + # user = User.find_by(username: 'alice') + # service = AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(some_user) + # service.execute + class FindRecordsDueForRefreshService + def initialize(user, source: nil, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil) + @user = user + @source = source + @incorrect_auth_found_callback = incorrect_auth_found_callback + @missing_auth_found_callback = missing_auth_found_callback + end + + def execute + current = current_authorizations_per_project + fresh = fresh_access_levels_per_project + + # Projects that have more than one authorizations associated with + # the user needs to be deleted. + # The correct authorization is added to the ``add`` array in the + # next stage. + remove = projects_with_duplicates + current.except!(*projects_with_duplicates) + + remove |= current.each_with_object([]) do |(project_id, row), array| + # rows not in the new list or with a different access level should be + # removed. + if !fresh[project_id] || fresh[project_id] != row.access_level + if incorrect_auth_found_callback + incorrect_auth_found_callback.call(project_id, row.access_level) + end + + array << row.project_id + end + end + + add = fresh.each_with_object([]) do |(project_id, level), array| + # rows not in the old list or with a different access level should be + # added. + if !current[project_id] || current[project_id].access_level != level + if missing_auth_found_callback + missing_auth_found_callback.call(project_id, level) + end + + array << [user.id, project_id, level] + end + end + + [remove, add] + end + + def fresh_access_levels_per_project + fresh_authorizations.each_with_object({}) do |row, hash| + hash[row.project_id] = row.access_level + end + end + + def current_authorizations_per_project + current_authorizations.index_by(&:project_id) + end + + def current_authorizations + @current_authorizations ||= user.project_authorizations.select(:project_id, :access_level) + end + + def fresh_authorizations + Gitlab::ProjectAuthorizations.new(user).calculate + end + + private + + attr_reader :user, :source, :incorrect_auth_found_callback, :missing_auth_found_callback + + def projects_with_duplicates + @projects_with_duplicates ||= current_authorizations + .group_by(&:project_id) + .select { |project_id, authorizations| authorizations.count > 1 } + .keys + end + end +end |