Merge branch 'project-specific-lfs' into 'master'

Added project specific enable/disable setting for LFS

## What does this MR do?

Adds project specific enable/disable setting for LFS

## What are the relevant issue numbers?

Needed for #18092

See merge request !5997
This commit is contained in:
Robert Speicher 2016-08-30 23:01:26 +00:00
commit 88295e0742
15 changed files with 208 additions and 6 deletions

View file

@ -25,6 +25,7 @@ v 8.12.0 (unreleased)
- Add horizontal scrolling to all sub-navs on mobile viewports (ClemMakesApps)
- Fix markdown help references (ClemMakesApps)
- Add last commit time to repo view (ClemMakesApps)
- Added project specific enable/disable setting for LFS !5997
- Added tests for diff notes
- Add a button to download latest successful artifacts for branches and tags !5142
- Add delimiter to project stars and forks count (ClemMakesApps)

View file

@ -311,6 +311,14 @@ a.deploy-project-label {
color: $gl-success;
}
.lfs-enabled {
color: $gl-success;
}
.lfs-disabled {
color: $gl-warning;
}
.breadcrumb.repo-breadcrumb {
padding: 0;
background: transparent;

View file

@ -309,7 +309,7 @@ class ProjectsController < Projects::ApplicationController
:issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled
:public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, :lfs_enabled
)
end

View file

@ -23,10 +23,14 @@ module LfsHelper
end
def lfs_download_access?
return false unless project.lfs_enabled?
project.public? || ci? || (user && user.can?(:download_code, project))
end
def lfs_upload_access?
return false unless project.lfs_enabled?
user && user.can?(:push_code, project)
end

View file

@ -187,6 +187,18 @@ module ProjectsHelper
nav_tabs.flatten
end
def project_lfs_status(project)
if project.lfs_enabled?
content_tag(:span, class: 'lfs-enabled') do
'Enabled'
end
else
content_tag(:span, class: 'lfs-disabled') do
'Disabled'
end
end
end
def git_user_name
if current_user
current_user.name

View file

@ -390,6 +390,13 @@ class Project < ActiveRecord::Base
end
end
def lfs_enabled?
return false unless Gitlab.config.lfs.enabled
return Gitlab.config.lfs.enabled if self[:lfs_enabled].nil?
self[:lfs_enabled]
end
def repository_storage_path
Gitlab.config.repositories.storages[repository_storage]
end

View file

@ -73,6 +73,12 @@
%span.light last commit:
%strong
= last_commit(@project)
%li
%span.light Git LFS status:
%strong
= project_lfs_status(@project)
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
- else
%li
%span.light repository:

View file

@ -80,6 +80,16 @@
%strong Snippets
%br
%span.descr Share code pastes with others out of git repository
- if Gitlab.config.lfs.enabled && current_user.admin?
.form-group
.checkbox
= f.label :lfs_enabled do
= f.check_box :lfs_enabled, checked: @project.lfs_enabled?
%strong LFS
%br
%span.descr
Git Large File Storage
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
- if Gitlab.config.registry.enabled
.form-group
.checkbox

View file

@ -0,0 +1,29 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddLfsEnabledToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index" or "add_column_with_default"
# you must disable the use of transactions as these methods can not run in an
# existing transaction. When using "add_concurrent_index" make sure that this
# method is the _only_ method called in the migration, any other changes
# should go in a separate migration. This ensures that upon failure _only_ the
# index creation fails and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
# disable_ddl_transaction!
def change
add_column :projects, :lfs_enabled, :boolean
end
end

View file

@ -825,6 +825,7 @@ ActiveRecord::Schema.define(version: 20160827011312) do
t.string "repository_storage", default: "default", null: false
t.boolean "request_access_enabled", default: true, null: false
t.boolean "has_external_wiki"
t.boolean "lfs_enabled"
end
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree

View file

@ -452,6 +452,7 @@ Parameters:
- `import_url` (optional)
- `public_builds` (optional)
- `only_allow_merge_if_build_succeeds` (optional)
- `lfs_enabled` (optional)
### Create project for user
@ -478,6 +479,7 @@ Parameters:
- `import_url` (optional)
- `public_builds` (optional)
- `only_allow_merge_if_build_succeeds` (optional)
- `lfs_enabled` (optional)
### Edit project
@ -505,6 +507,7 @@ Parameters:
- `visibility_level` (optional)
- `public_builds` (optional)
- `only_allow_merge_if_build_succeeds` (optional)
- `lfs_enabled` (optional)
On success, method returns 200 with the updated project. If parameters are
invalid, 400 is returned.

View file

@ -32,4 +32,12 @@ Snippets are little bits of code or text.
This is a nice place to put code or text that is used semi-regularly within the project, but does not belong in source control.
For example, a specific config file that is used by > the team that is only valid for the people that work on the code.
For example, a specific config file that is used by the team that is only valid for the people that work on the code.
## Git LFS
>**Note:** Project-specific LFS setting was added on 8.12 and is available only to admins.
Git Large File Storage allows you to easily manage large binary files with Git.
With this setting admins can better control which projects are allowed to use
LFS.

View file

@ -78,7 +78,7 @@ module API
expose :path, :path_with_namespace
expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :container_registry_enabled
expose :created_at, :last_activity_at
expose :shared_runners_enabled
expose :shared_runners_enabled, :lfs_enabled
expose :creator_id
expose :namespace
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? }

View file

@ -105,6 +105,7 @@ module API
# visibility_level (optional) - 0 by default
# import_url (optional)
# public_builds (optional)
# lfs_enabled (optional)
# Example Request
# POST /projects
post do
@ -124,7 +125,8 @@ module API
:visibility_level,
:import_url,
:public_builds,
:only_allow_merge_if_build_succeeds]
:only_allow_merge_if_build_succeeds,
:lfs_enabled]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateService.new(current_user, attrs).execute
if @project.saved?
@ -156,6 +158,7 @@ module API
# visibility_level (optional)
# import_url (optional)
# public_builds (optional)
# lfs_enabled (optional)
# Example Request
# POST /projects/user/:user_id
post "user/:user_id" do
@ -174,7 +177,8 @@ module API
:visibility_level,
:import_url,
:public_builds,
:only_allow_merge_if_build_succeeds]
:only_allow_merge_if_build_succeeds,
:lfs_enabled]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateService.new(user, attrs).execute
if @project.saved?
@ -220,6 +224,7 @@ module API
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - visibility level of a project
# public_builds (optional)
# lfs_enabled (optional)
# Example Request
# PUT /projects/:id
put ':id' do
@ -237,7 +242,8 @@ module API
:public,
:visibility_level,
:public_builds,
:only_allow_merge_if_build_succeeds]
:only_allow_merge_if_build_succeeds,
:lfs_enabled]
attrs = map_public_to_visibility_level(attrs)
authorize_admin_project
authorize! :rename_project, user_project if attrs[:name].present?

View file

@ -44,6 +44,113 @@ describe 'Git LFS API and storage' do
end
end
context 'project specific LFS settings' do
let(:project) { create(:empty_project) }
let(:body) do
{
'objects' => [
{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078
},
{ 'oid' => sample_oid,
'size' => sample_size
}
],
'operation' => 'upload'
}
end
let(:authorization) { authorize_user }
context 'with LFS disabled globally' do
before do
project.team << [user, :master]
allow(Gitlab.config.lfs).to receive(:enabled).and_return(false)
end
describe 'LFS disabled in project' do
before do
project.update_attribute(:lfs_enabled, false)
end
it 'responds with a 501 message on upload' do
post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
expect(response).to have_http_status(501)
end
it 'responds with a 501 message on download' do
get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
expect(response).to have_http_status(501)
end
end
describe 'LFS enabled in project' do
before do
project.update_attribute(:lfs_enabled, true)
end
it 'responds with a 501 message on upload' do
post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
expect(response).to have_http_status(501)
end
it 'responds with a 501 message on download' do
get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
expect(response).to have_http_status(501)
end
end
end
context 'with LFS enabled globally' do
before do
project.team << [user, :master]
enable_lfs
end
describe 'LFS disabled in project' do
before do
project.update_attribute(:lfs_enabled, false)
end
it 'responds with a 403 message on upload' do
post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
expect(response).to have_http_status(403)
expect(json_response).to include('message' => 'Access forbidden. Check your access level.')
end
it 'responds with a 403 message on download' do
get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
expect(response).to have_http_status(403)
expect(json_response).to include('message' => 'Access forbidden. Check your access level.')
end
end
describe 'LFS enabled in project' do
before do
project.update_attribute(:lfs_enabled, true)
end
it 'responds with a 200 message on upload' do
post_lfs_json "#{project.http_url_to_repo}/info/lfs/objects/batch", body, headers
expect(response).to have_http_status(200)
expect(json_response['objects'].first['size']).to eq(1575078)
end
it 'responds with a 200 message on download' do
get "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", nil, headers
expect(response).to have_http_status(200)
end
end
end
end
describe 'deprecated API' do
let(:project) { create(:empty_project) }