Commit 69b2ac80 authored by huzaifaiftikhar1's avatar huzaifaiftikhar1

Remove projects that are marked for deletion from UI

Projects that are marked for deletion will not be accessible
anywhere except the interfaces designed to list projects
marked for deletion.

Changelog: changed
parent eedf9b63
...@@ -35,7 +35,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -35,7 +35,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def starred def starred
@projects = load_projects(params.merge(starred: true)) @projects = load_projects(params.merge({ starred: true, not_aimed_for_deletion: true }))
.includes(:forked_from_project, :topics) .includes(:forked_from_project, :topics)
@groups = [] @groups = []
...@@ -54,7 +54,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -54,7 +54,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
private private
def projects def projects
@projects ||= load_projects(params.merge(non_public: true)) @projects ||= load_projects(params.merge(non_public: true, not_aimed_for_deletion: true))
end end
def render_projects def render_projects
...@@ -65,8 +65,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -65,8 +65,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end end
def load_projects(finder_params) def load_projects(finder_params)
@total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true }, current_user: current_user).execute @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute
@total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true }, current_user: current_user).execute @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute
finder_params[:use_cte] = true if use_cte_for_finder? finder_params[:use_cte] = true if use_cte_for_finder?
finder_params[:without_deleted] = true finder_params[:without_deleted] = true
......
...@@ -92,7 +92,12 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -92,7 +92,12 @@ class Explore::ProjectsController < Explore::ApplicationController
def load_projects def load_projects
load_project_counts load_project_counts
projects = ProjectsFinder.new(current_user: current_user, params: params.merge(minimum_search_length: MIN_SEARCH_LENGTH)).execute finder_params = {
minimum_search_length: MIN_SEARCH_LENGTH,
not_aimed_for_deletion: true
}
projects = ProjectsFinder.new(current_user: current_user, params: params.merge(finder_params)).execute
projects = preload_associations(projects) projects = preload_associations(projects)
projects = projects.page(params[:page]).without_count projects = projects.page(params[:page]).without_count
......
...@@ -186,7 +186,7 @@ class UsersController < ApplicationController ...@@ -186,7 +186,7 @@ class UsersController < ApplicationController
end end
def starred_projects def starred_projects
StarredProjectsFinder.new(user, current_user: current_user).execute StarredProjectsFinder.new(user, params: finder_params, current_user: current_user).execute
end end
def contributions_calendar def contributions_calendar
...@@ -252,6 +252,15 @@ class UsersController < ApplicationController ...@@ -252,6 +252,15 @@ class UsersController < ApplicationController
end end
end end
end end
def finder_params
{
# don't display projects pending deletion
without_deleted: true,
# don't display projects marked for deletion
not_aimed_for_deletion: true
}
end
end end
UsersController.prepend_mod_with('UsersController') UsersController.prepend_mod_with('UsersController')
...@@ -25,7 +25,7 @@ class GroupDescendantsFinder ...@@ -25,7 +25,7 @@ class GroupDescendantsFinder
def initialize(current_user: nil, parent_group:, params: {}) def initialize(current_user: nil, parent_group:, params: {})
@current_user = current_user @current_user = current_user
@parent_group = parent_group @parent_group = parent_group
@params = params.reverse_merge(non_archived: params[:archived].blank?) @params = params.reverse_merge(non_archived: params[:archived].blank?, not_aimed_for_deletion: true)
end end
def execute def execute
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
# last_activity_before: datetime # last_activity_before: datetime
# repository_storage: string # repository_storage: string
# without_deleted: boolean # without_deleted: boolean
# not_aimed_for_deletion: boolean
# #
class ProjectsFinder < UnionFinder class ProjectsFinder < UnionFinder
include CustomAttributesFilter include CustomAttributesFilter
...@@ -84,6 +85,7 @@ class ProjectsFinder < UnionFinder ...@@ -84,6 +85,7 @@ class ProjectsFinder < UnionFinder
collection = by_archived(collection) collection = by_archived(collection)
collection = by_custom_attributes(collection) collection = by_custom_attributes(collection)
collection = by_deleted_status(collection) collection = by_deleted_status(collection)
collection = by_not_aimed_for_deletion(collection)
collection = by_last_activity_after(collection) collection = by_last_activity_after(collection)
collection = by_last_activity_before(collection) collection = by_last_activity_before(collection)
by_repository_storage(collection) by_repository_storage(collection)
...@@ -203,6 +205,10 @@ class ProjectsFinder < UnionFinder ...@@ -203,6 +205,10 @@ class ProjectsFinder < UnionFinder
params[:without_deleted].present? ? items.without_deleted : items params[:without_deleted].present? ? items.without_deleted : items
end end
def by_not_aimed_for_deletion(items)
params[:not_aimed_for_deletion].present? ? items.not_aimed_for_deletion : items
end
def by_last_activity_after(items) def by_last_activity_after(items)
if params[:last_activity_after].present? if params[:last_activity_after].present?
items.where("last_activity_at > ?", params[:last_activity_after]) # rubocop: disable CodeReuse/ActiveRecord items.where("last_activity_at > ?", params[:last_activity_after]) # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -511,6 +511,7 @@ class Project < ApplicationRecord ...@@ -511,6 +511,7 @@ class Project < ApplicationRecord
# Scopes # Scopes
scope :pending_delete, -> { where(pending_delete: true) } scope :pending_delete, -> { where(pending_delete: true) }
scope :without_deleted, -> { where(pending_delete: false) } scope :without_deleted, -> { where(pending_delete: false) }
scope :not_aimed_for_deletion, -> { where(marked_for_deletion_at: nil).without_deleted }
scope :with_storage_feature, ->(feature) do scope :with_storage_feature, ->(feature) do
where(arel_table[:storage_version].gteq(HASHED_STORAGE_FEATURES[feature])) where(arel_table[:storage_version].gteq(HASHED_STORAGE_FEATURES[feature]))
......
...@@ -1593,7 +1593,7 @@ class User < ApplicationRecord ...@@ -1593,7 +1593,7 @@ class User < ApplicationRecord
.distinct .distinct
.reorder(nil) .reorder(nil)
Project.where(id: events) Project.where(id: events).not_aimed_for_deletion
end end
def can_be_removed? def can_be_removed?
......
...@@ -158,7 +158,6 @@ module EE ...@@ -158,7 +158,6 @@ module EE
scope :with_slack_integration, -> { joins(:slack_integration) } scope :with_slack_integration, -> { joins(:slack_integration) }
scope :with_slack_slash_commands_integration, -> { joins(:slack_slash_commands_integration) } scope :with_slack_slash_commands_integration, -> { joins(:slack_slash_commands_integration) }
scope :aimed_for_deletion, -> (date) { where('marked_for_deletion_at <= ?', date).without_deleted } scope :aimed_for_deletion, -> (date) { where('marked_for_deletion_at <= ?', date).without_deleted }
scope :not_aimed_for_deletion, -> { where(marked_for_deletion_at: nil) }
scope :with_repos_templates, -> { where(namespace_id: ::Gitlab::CurrentSettings.current_application_settings.custom_project_templates_group_id) } scope :with_repos_templates, -> { where(namespace_id: ::Gitlab::CurrentSettings.current_application_settings.custom_project_templates_group_id) }
scope :with_groups_level_repos_templates, -> { joins("INNER JOIN namespaces ON projects.namespace_id = namespaces.custom_project_templates_group_id") } scope :with_groups_level_repos_templates, -> { joins("INNER JOIN namespaces ON projects.namespace_id = namespaces.custom_project_templates_group_id") }
scope :with_designs, -> { where(id: ::DesignManagement::Design.select(:project_id).distinct) } scope :with_designs, -> { where(id: ::DesignManagement::Design.select(:project_id).distinct) }
......
...@@ -57,6 +57,14 @@ RSpec.describe ProjectsFinder do ...@@ -57,6 +57,14 @@ RSpec.describe ProjectsFinder do
it { is_expected.to contain_exactly(aimed_for_deletion_project) } it { is_expected.to contain_exactly(aimed_for_deletion_project) }
end end
context 'filter by not aimed for deletion' do
let_it_be(:params) { { not_aimed_for_deletion: true } }
let_it_be(:aimed_for_deletion_project) { create(:project, :public, marked_for_deletion_at: 2.days.ago, pending_delete: false) }
let_it_be(:deleted_project) { create(:project, :public, marked_for_deletion_at: 1.month.ago, pending_delete: true) }
it { is_expected.to contain_exactly(ultimate_project, ultimate_project2, premium_project, no_plan_project) }
end
private private
def create_project(plan) def create_project(plan)
......
...@@ -97,14 +97,18 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do ...@@ -97,14 +97,18 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
subject { get :starred, format: :json } subject { get :starred, format: :json }
let(:projects) { create_list(:project, 2, creator: user) } let(:projects) { create_list(:project, 2, creator: user) }
let(:pending_deletion_project) { create_list(:project, 2, :archived, creator: user, marked_for_deletion_at: 3.days.ago) }
before do before do
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
projects.each do |project| projects.each do |project|
project.add_developer(user) project.add_developer(user)
create(:users_star_project, project_id: project.id, user_id: user.id) create(:users_star_project, project_id: project.id, user_id: user.id)
end end
pending_deletion_project.each do |project|
project.add_developer(user)
create(:users_star_project, project_id: project.id, user_id: user.id)
end
end end
it 'returns success' do it 'returns success' do
...@@ -113,10 +117,22 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do ...@@ -113,10 +117,22 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
it 'paginates the records' do context "pagination" do
before do
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
end
it 'paginates the records' do
subject
expect(assigns(:projects).count).to eq(1)
end
end
it 'does not include projects pending deletion' do
subject subject
expect(assigns(:projects).count).to eq(1) expect(assigns(:projects).count).to eq(2)
end end
end end
end end
......
...@@ -73,6 +73,24 @@ RSpec.describe Explore::ProjectsController do ...@@ -73,6 +73,24 @@ RSpec.describe Explore::ProjectsController do
expect(assigns(:projects)).to eq [project1, project2] expect(assigns(:projects)).to eq [project1, project2]
end end
end end
context 'projects pending deletion' do
let(:project1) { create(:project, :public, updated_at: 3.days.ago) }
let(:project2) { create(:project, :public, updated_at: 1.day.ago) }
let(:pending_deletion_project) { create(:project, :public, :archived, updated_at: 2.days.ago, marked_for_deletion_at: 2.days.ago) }
before do
create(:trending_project, project: project1)
create(:trending_project, project: project2)
create(:trending_project, project: pending_deletion_project)
end
it 'does not list projects pending deletion' do
get :trending
expect(assigns(:projects)).to eq [project2, project1]
end
end
end end
describe 'GET #topic' do describe 'GET #topic' do
......
...@@ -68,6 +68,12 @@ RSpec.describe GroupDescendantsFinder do ...@@ -68,6 +68,12 @@ RSpec.describe GroupDescendantsFinder do
expect(finder.execute).to be_empty expect(finder.execute).to be_empty
end end
it 'does not include projects pending deletion' do
_project_aimed_for_deletion = create(:project, :archived, marked_for_deletion_at: 2.days.ago, pending_delete: false)
expect(finder.execute).to be_empty
end
context 'with a filter' do context 'with a filter' do
let(:params) { { filter: 'test' } } let(:params) { { filter: 'test' } }
......
...@@ -3602,13 +3602,16 @@ RSpec.describe User do ...@@ -3602,13 +3602,16 @@ RSpec.describe User do
let!(:project1) { create(:project) } let!(:project1) { create(:project) }
let!(:project2) { fork_project(project3) } let!(:project2) { fork_project(project3) }
let!(:project3) { create(:project) } let!(:project3) { create(:project) }
let!(:project_pending_deletion) { create(:project, marked_for_deletion_at: 2.days.ago, pending_delete: false) }
let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) } let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) }
let!(:push_event) { create(:push_event, project: project1, author: subject) } let!(:push_event) { create(:push_event, project: project1, author: subject) }
let!(:merge_event) { create(:event, :created, project: project3, target: merge_request, author: subject) } let!(:merge_event) { create(:event, :created, project: project3, target: merge_request, author: subject) }
let!(:merge_event_2) { create(:event, :created, project: project_pending_deletion, target: merge_request, author: subject) }
before do before do
project1.add_maintainer(subject) project1.add_maintainer(subject)
project2.add_maintainer(subject) project2.add_maintainer(subject)
project_pending_deletion.add_maintainer(subject)
end end
it 'includes IDs for projects the user has pushed to' do it 'includes IDs for projects the user has pushed to' do
...@@ -3622,6 +3625,10 @@ RSpec.describe User do ...@@ -3622,6 +3625,10 @@ RSpec.describe User do
it "doesn't include IDs for unrelated projects" do it "doesn't include IDs for unrelated projects" do
expect(subject.contributed_projects).not_to include(project2) expect(subject.contributed_projects).not_to include(project2)
end end
it "doesn't include projects pending deletion" do
expect(subject.contributed_projects).not_to include(project_pending_deletion)
end
end end
describe '#fork_of' do describe '#fork_of' do
......
...@@ -506,6 +506,7 @@ RSpec.describe UsersController do ...@@ -506,6 +506,7 @@ RSpec.describe UsersController do
describe 'GET #contributed' do describe 'GET #contributed' do
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let(:pending_deletion_project) { create(:project, :public, :archived, marked_for_deletion_at: 3.days.ago) }
subject do subject do
get user_contributed_projects_url author.username, format: format get user_contributed_projects_url author.username, format: format
...@@ -516,7 +517,10 @@ RSpec.describe UsersController do ...@@ -516,7 +517,10 @@ RSpec.describe UsersController do
project.add_developer(public_user) project.add_developer(public_user)
project.add_developer(private_user) project.add_developer(private_user)
pending_deletion_project.add_developer(public_user)
pending_deletion_project.add_developer(private_user)
create(:push_event, project: project, author: author) create(:push_event, project: project, author: author)
create(:push_event, project: pending_deletion_project, author: author)
subject subject
end end
...@@ -526,6 +530,11 @@ RSpec.describe UsersController do ...@@ -526,6 +530,11 @@ RSpec.describe UsersController do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response.body).not_to be_empty expect(response.body).not_to be_empty
end end
it 'does not list projects pending deletion' do
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:contributed_projects)).to eq([project])
end
end end
%i(html json).each do |format| %i(html json).each do |format|
...@@ -557,6 +566,7 @@ RSpec.describe UsersController do ...@@ -557,6 +566,7 @@ RSpec.describe UsersController do
describe 'GET #starred' do describe 'GET #starred' do
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let(:pending_deletion_project) { create(:project, :public, :archived, marked_for_deletion_at: 3.days.ago) }
subject do subject do
get user_starred_projects_url author.username, format: format get user_starred_projects_url author.username, format: format
...@@ -574,6 +584,11 @@ RSpec.describe UsersController do ...@@ -574,6 +584,11 @@ RSpec.describe UsersController do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response.body).not_to be_empty expect(response.body).not_to be_empty
end end
it 'does not list projects pending deletion' do
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:starred_projects)).to eq([project])
end
end end
%i(html json).each do |format| %i(html json).each do |format|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment