Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSean McGivern <sean@mcgivern.me.uk>2018-08-07 20:16:10 +0300
committerSean McGivern <sean@mcgivern.me.uk>2018-08-07 20:16:10 +0300
commit21c18070283041fb016777493d61b42edac600e5 (patch)
treeb28d7cfd32b9d1cefc9b2b9c9c59ce31377466fc /lib
parent97eb1d5ae11d7a56b425f9894b5c6a87c1ec055d (diff)
parent8338f9b89bfbc2e2db28041b271f471ed7a7960e (diff)
Merge branch 'todos-visibility-migration' into 'master'
Remove todos of users without access to targets (migration) See merge request gitlab-org/gitlab-ce!20927
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/background_migration/remove_restricted_todos.rb105
1 files changed, 105 insertions, 0 deletions
diff --git a/lib/gitlab/background_migration/remove_restricted_todos.rb b/lib/gitlab/background_migration/remove_restricted_todos.rb
new file mode 100644
index 00000000000..68f3fa62170
--- /dev/null
+++ b/lib/gitlab/background_migration/remove_restricted_todos.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class RemoveRestrictedTodos
+ PRIVATE_FEATURE = 10
+ PRIVATE_PROJECT = 0
+
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+ end
+
+ class ProjectAuthorization < ActiveRecord::Base
+ self.table_name = 'project_authorizations'
+ end
+
+ class ProjectFeature < ActiveRecord::Base
+ self.table_name = 'project_features'
+ end
+
+ class Todo < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'todos'
+ end
+
+ class Issue < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'issues'
+ end
+
+ def perform(start_id, stop_id)
+ projects = Project.where('EXISTS (SELECT 1 FROM todos WHERE todos.project_id = projects.id)')
+ .where(id: start_id..stop_id)
+
+ projects.each do |project|
+ remove_confidential_issue_todos(project.id)
+
+ if project.visibility_level == PRIVATE_PROJECT
+ remove_non_members_todos(project.id)
+ else
+ remove_restricted_features_todos(project.id)
+ end
+ end
+ end
+
+ private
+
+ def remove_non_members_todos(project_id)
+ Todo.where(project_id: project_id)
+ .where('user_id NOT IN (?)', authorized_users(project_id))
+ .each_batch(of: 5000) do |batch|
+ batch.delete_all
+ end
+ end
+
+ def remove_confidential_issue_todos(project_id)
+ # min access level to access a confidential issue is reporter
+ min_reporters = authorized_users(project_id)
+ .select(:user_id)
+ .where('access_level >= ?', 20)
+
+ confidential_issues = Issue.select(:id, :author_id).where(confidential: true, project_id: project_id)
+ confidential_issues.each_batch(of: 100) do |batch|
+ batch.each do |issue|
+ assigned_users = IssueAssignee.select(:user_id).where(issue_id: issue.id)
+
+ todos = Todo.where(target_type: 'Issue', target_id: issue.id)
+ .where('user_id NOT IN (?)', min_reporters)
+ .where('user_id NOT IN (?)', assigned_users)
+ todos = todos.where('user_id != ?', issue.author_id) if issue.author_id
+
+ todos.delete_all
+ end
+ end
+ end
+
+ def remove_restricted_features_todos(project_id)
+ ProjectFeature.where(project_id: project_id).each do |project_features|
+ target_types = []
+ target_types << 'Issue' if private?(project_features.issues_access_level)
+ target_types << 'MergeRequest' if private?(project_features.merge_requests_access_level)
+ target_types << 'Commit' if private?(project_features.repository_access_level)
+
+ next if target_types.empty?
+
+ Todo.where(project_id: project_id)
+ .where('user_id NOT IN (?)', authorized_users(project_id))
+ .where(target_type: target_types)
+ .delete_all
+ end
+ end
+
+ def private?(feature_level)
+ feature_level == PRIVATE_FEATURE
+ end
+
+ def authorized_users(project_id)
+ ProjectAuthorization.select(:user_id).where(project_id: project_id)
+ end
+ end
+ end
+end