Read about our upcoming Code of Conduct on this issue

This instance will be upgraded to Heptapod 0.28.1 on 2022-01-26 at 16:00 UTC+1 (a few minutes of down time)

Commit f40ad6ce authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets
Browse files

Merge pull request #5841 from Popl7/archiving_old_projects

Archiving old projects for feature request
......@@ -73,6 +73,6 @@ def issues
protected
def load_projects
@projects = current_user.authorized_projects.sorted_by_activity
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
end
end
......@@ -5,7 +5,7 @@ class ProjectsController < ApplicationController
# Authorize
before_filter :authorize_read_project!, except: [:index, :new, :create]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
before_filter :require_non_empty_project, only: [:blob, :tree, :graph]
layout 'navless', only: [:new, :create, :fork]
......@@ -116,6 +116,24 @@ def autocomplete_sources
end
end
def archive
return access_denied! unless can?(current_user, :archive_project, project)
project.archive!
respond_to do |format|
format.html { redirect_to @project }
end
end
def unarchive
return access_denied! unless can?(current_user, :archive_project, project)
project.unarchive!
respond_to do |format|
format.html { redirect_to @project }
end
end
private
def set_title
......
......@@ -73,14 +73,14 @@ def groups_autocomplete
# Autocomplete results for the current user's projects
def projects_autocomplete
current_user.authorized_projects.map do |p|
current_user.authorized_projects.non_archived.map do |p|
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
end
end
# Autocomplete results for the current user's projects
def public_projects_autocomplete
Project.public_or_internal_only(current_user).map do |p|
Project.public_or_internal_only(current_user).non_archived.map do |p|
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
end
end
......
......@@ -59,31 +59,35 @@ def project_abilities(user, project)
# Rules based on role in project
if team.masters.include?(user)
rules << project_master_rules
rules += project_master_rules
elsif team.developers.include?(user)
rules << project_dev_rules
rules += project_dev_rules
elsif team.reporters.include?(user)
rules << project_report_rules
rules += project_report_rules
elsif team.guests.include?(user)
rules << project_guest_rules
rules += project_guest_rules
end
if project.public? || project.internal?
rules << public_project_rules
rules += public_project_rules
end
if project.owner == user || user.admin?
rules << project_admin_rules
rules += project_admin_rules
end
if project.group && project.group.has_owner?(user)
rules << project_admin_rules
rules += project_admin_rules
end
rules.flatten
if project.archived?
rules -= project_archived_rules
end
rules
end
def public_project_rules
......@@ -125,6 +129,16 @@ def project_dev_rules
]
end
def project_archived_rules
[
:write_merge_request,
:push_code,
:push_code_to_protected_branches,
:modify_merge_request,
:admin_merge_request
]
end
def project_master_rules
project_dev_rules + [
:push_code_to_protected_branches,
......@@ -147,7 +161,8 @@ def project_admin_rules
:change_namespace,
:change_visibility_level,
:rename_project,
:remove_project
:remove_project,
:archive_project
]
end
......@@ -160,7 +175,7 @@ def group_abilities user, group
# Only group owner and administrators can manage group
if group.has_owner?(user) || user.admin?
rules << [
rules += [
:manage_group,
:manage_namespace
]
......@@ -174,7 +189,7 @@ def namespace_abilities user, namespace
# Only namespace owner and administrators can manage it
if namespace.owner == user || user.admin?
rules << [
rules += [
:manage_namespace
]
end
......
......@@ -116,6 +116,8 @@ class Project < ActiveRecord::Base
scope :public_only, -> { where(visibility_level: PUBLIC) }
scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) }
scope :non_archived, -> { where(archived: false) }
enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
class << self
......@@ -132,7 +134,7 @@ def active
end
def search query
joins(:namespace).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%")
joins(:namespace).where("projects.archived = ?", false).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%")
end
def find_with_namespace(id)
......@@ -472,4 +474,12 @@ def reload_default_branch
def visibility_level_field
visibility_level
end
def archive!
update_attribute(:archived, true)
end
def unarchive!
update_attribute(:archived, false)
end
end
......@@ -82,6 +82,10 @@
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
.project-info
.pull-right
- if project.archived?
%span.label
%i.icon-book
Archived
- project.labels.each do |label|
%span.label.label-info
%i.icon-tag
......
......@@ -7,6 +7,10 @@
%span.visibility-level-label
= visibility_level_icon(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
- if @project.archived?
%span.visibility-level-label
%i.icon-book
Archived
.span7
- unless empty_repo
......
......@@ -98,6 +98,33 @@
%i.icon-chevron-down
.js-toggle-visibility-container.hide
- if can? current_user, :archive_project, @project
.ui-box.ui-box-danger
.title
- if @project.archived?
Unarchive project
- else
Archive project
.ui-box-body
- if @project.archived?
%p
Unarchiving the project will mark its repository as active.
%br
The project can be committed to.
%br
%strong Once active this project shows up in the search and on the dashboard.
= link_to 'Unarchive', unarchive_project_path(@project), confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be comitted to again.", method: :post, class: "btn btn-remove"
- else
%p
Archiving the project will mark its repository as read-only.
%br
It is hidden from the dashboard and doesn't show up in searches.
%br
%strong Archived projects cannot be committed to!
= link_to 'Archive', archive_project_path(@project), confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to.", method: :post, class: "btn btn-remove"
- else
%p.nothing_here_message Only the project owner can archive a project
- if can?(current_user, :change_namespace, @project)
.ui-box.ui-box-danger
.title Transfer project
......
......@@ -170,6 +170,8 @@
member do
put :transfer
post :fork
post :archive
post :unarchive
get :autocomplete_sources
end
......
class AddArchivedToProjects < ActiveRecord::Migration
def change
add_column :projects, :archived, :boolean, default: false, null: false
end
end
......@@ -192,6 +192,7 @@
t.boolean "imported", default: false, null: false
t.string "import_url"
t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false
end
add_index "projects", ["creator_id"], name: "index_projects_on_owner_id", using: :btree
......
Feature: Dashboard with archived projects
Background:
Given I sign in as a user
And I own project "Shop"
And I own project "Forum"
And project "Forum" is archived
And I visit dashboard page
Scenario: I should see non-archived projects on dashboard
Then I should see "Shop" project link
And I should not see "Forum" project link
Scenario: I should see all projects on projects page
And I visit dashboard projects page
Then I should see "Shop" project link
And I should see "Forum" project link
Feature: Project Archived
Background:
Given I sign in as a user
And I own project "Shop"
And I own project "Forum"
Scenario: I should not see archived on project page of not-archive project
And project "Forum" is archived
And I visit project "Shop" page
Then I should not see "Archived"
Scenario: I should see archived on project page of archive project
And project "Forum" is archived
And I visit project "Forum" page
Then I should see "Archived"
Scenario: I should not see archived on projects page with no archived projects
And I visit dashboard projects page
Then I should not see "Archived"
Scenario: I should see archived on projects page with archived projects
And project "Forum" is archived
And I visit dashboard projects page
Then I should see "Archived"
Scenario: I archive project
When project "Shop" has push event
And I visit project "Shop" page
And I visit edit project "Shop" page
And I set project archived
Then I should see "Archived"
Scenario: I unarchive project
When project "Shop" has push event
And project "Shop" is archived
And I visit project "Shop" page
And I visit edit project "Shop" page
And I set project unarchived
Then I should not see "Archived"
class DashboardWithArchivedProjects < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedProject
When 'project "Forum" is archived' do
project = Project.find_by_name "Forum"
project.update_attribute(:archived, true)
end
Then 'I should see "Shop" project link' do
page.should have_link "Shop"
end
Then 'I should not see "Forum" project link' do
page.should_not have_link "Forum"
end
Then 'I should see "Forum" project link' do
page.should have_link "Forum"
end
end
class ProjectArchived < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
When 'project "Forum" is archived' do
project = Project.find_by_name "Forum"
project.update_attribute(:archived, true)
end
When 'project "Shop" is archived' do
project = Project.find_by_name "Shop"
project.update_attribute(:archived, true)
end
When 'I visit project "Forum" page' do
project = Project.find_by_name "Forum"
visit project_path(project)
end
Then 'I should not see "Archived"' do
page.should_not have_content "Archived"
end
Then 'I should see "Archived"' do
page.should have_content "Archived"
end
When 'I set project archived' do
click_link "Archive"
end
When 'I set project unarchived' do
click_link "Unarchive"
end
end
\ No newline at end of file
......@@ -14,6 +14,13 @@ module SharedProject
@project.team << [@user, :master]
end
# Create another specific project called "Forum"
And 'I own project "Forum"' do
@project = Project.find_by_name "Forum"
@project ||= create(:project_with_code, name: "Forum", namespace: @user.namespace, path: 'forum_project')
@project.team << [@user, :master]
end
And 'project "Shop" has push event' do
@project = Project.find_by_name("Shop")
......
......@@ -21,6 +21,7 @@
# imported :boolean default(FALSE), not null
# import_url :string(255)
# visibility_level :integer default(0), not null
# archived :boolean default(FALSE), not null
#
require 'spec_helper'
......
......@@ -103,6 +103,33 @@
end
end
context "archived project" do
let(:personal_project) { create(:project, namespace: user.namespace) }
before do
project.team << [user, :developer]
project.archive!
end
context "git pull" do
it do
pull(key, project)
response.status.should == 200
response.body.should == 'true'
end
end
context "git push" do
it do
push(key, project)
response.status.should == 200
response.body.should == 'false'
end
end
end
context "deploy key" do
let(:key) { create(:deploy_key) }
......
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