From 3b8daba127a5eec1fd3ab1d4c9042eddeaf4f5bd Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 19 Jan 2017 16:20:03 -0200 Subject: [PATCH 1/9] Properly convert values to deal with Bytes --- app/controllers/concerns/lfs_request.rb | 2 +- app/models/project.rb | 6 ++++-- lib/gitlab/git_access.rb | 2 +- lib/gitlab/repository_size_error.rb | 2 +- spec/lib/gitlab/repository_size_error_spec.rb | 4 ++-- spec/models/project_spec.rb | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb index f8f1e41c4229a2..0ded2e3c44ee29 100644 --- a/app/controllers/concerns/lfs_request.rb +++ b/app/controllers/concerns/lfs_request.rb @@ -136,7 +136,7 @@ def objects_exceed_repo_limit? size_of_objects = objects.sum { |o| o[:size] } - @limit_exceeded = (project.repository_and_lfs_size + size_of_objects.to_mb) > project.actual_size_limit + @limit_exceeded = (project.repository_and_lfs_size + size_of_objects) > project.actual_size_limit end end diff --git a/app/models/project.rb b/app/models/project.rb index 50f6576e2e2c87..d5f1d5cbc92fa9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1541,8 +1541,10 @@ def size_limit_enabled? actual_size_limit != 0 end - def changes_will_exceed_size_limit?(size_mb) - size_limit_enabled? && (size_mb > actual_size_limit || size_mb + repository_and_lfs_size > actual_size_limit) + def changes_will_exceed_size_limit?(size_in_bytes) + size_limit_enabled? && + (size_in_bytes > actual_size_limit || + size_in_bytes + repository_and_lfs_size > actual_size_limit) end def environments_for(ref, commit: nil, with_tags: false) diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 026725369a0004..89510c282e6e3d 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -185,7 +185,7 @@ def check_change_access!(changes) end end - if project.changes_will_exceed_size_limit?(push_size_in_bytes.to_mb) + if project.changes_will_exceed_size_limit?(push_size_in_bytes) raise UnauthorizedError, Gitlab::RepositorySizeError.new(project).new_changes_error end end diff --git a/lib/gitlab/repository_size_error.rb b/lib/gitlab/repository_size_error.rb index e9271cbd9b395f..c1dbd3b93edbf5 100644 --- a/lib/gitlab/repository_size_error.rb +++ b/lib/gitlab/repository_size_error.rb @@ -55,7 +55,7 @@ def size_to_remove end def format_number(number) - number_to_human_size(number * 1.megabyte, delimiter: ',', precision: 2) + number_to_human_size(number, delimiter: ',', precision: 2) end end end diff --git a/spec/lib/gitlab/repository_size_error_spec.rb b/spec/lib/gitlab/repository_size_error_spec.rb index b8312b43b8900f..5ee09b3093e162 100644 --- a/spec/lib/gitlab/repository_size_error_spec.rb +++ b/spec/lib/gitlab/repository_size_error_spec.rb @@ -2,14 +2,14 @@ describe Gitlab::RepositorySizeError, lib: true do let(:project) do - create(:empty_project, statistics: build(:project_statistics, repository_size: 15)) + create(:empty_project, statistics: build(:project_statistics, repository_size: 15.megabytes)) end let(:message) { Gitlab::RepositorySizeError.new(project) } let(:base_message) { 'because this repository has exceeded its size limit of 10 MB by 5 MB' } before do - allow(project).to receive(:actual_size_limit).and_return(10) + allow(project).to receive(:actual_size_limit).and_return(10.megabytes) end describe 'error messages' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index db6af6d2a9b6f6..810f38372224d6 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -573,13 +573,13 @@ group = create(:group, repository_size_limit: 100) project.update_attribute(:namespace_id, group.id) - expect(project.actual_size_limit).to eq(100) + expect(project.actual_size_limit).to eq(100.megabytes) end it 'returns the value set locally' do project.update_attribute(:repository_size_limit, 75) - expect(project.actual_size_limit).to eq(75) + expect(project.actual_size_limit).to eq(75.megabytes) end end -- GitLab From 930b098ca3a4c5a54991e7bc64de5ef310d98abe Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 19 Jan 2017 16:21:38 -0200 Subject: [PATCH 2/9] Save repository size limit as Bytes before saving it --- app/models/application_setting.rb | 1 + app/models/concerns/repository_size_limit.rb | 13 +++ app/models/group.rb | 1 + app/models/project.rb | 1 + .../concerns/repository_size_limit_spec.rb | 91 +++++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 app/models/concerns/repository_size_limit.rb create mode 100644 spec/models/concerns/repository_size_limit_spec.rb diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index d76f7481569d15..d38a2f810dbfee 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -2,6 +2,7 @@ class ApplicationSetting < ActiveRecord::Base include CacheMarkdownField include TokenAuthenticatable prepend EE::ApplicationSetting + include RepositorySizeLimit add_authentication_token_field :runners_registration_token add_authentication_token_field :health_check_access_token diff --git a/app/models/concerns/repository_size_limit.rb b/app/models/concerns/repository_size_limit.rb new file mode 100644 index 00000000000000..b80dda3d88cd10 --- /dev/null +++ b/app/models/concerns/repository_size_limit.rb @@ -0,0 +1,13 @@ +module RepositorySizeLimit + extend ActiveSupport::Concern + + included do + before_save :convert_from_megabytes_to_bytes, if: :repository_size_limit_changed? + end + + private + + def convert_from_megabytes_to_bytes + self.repository_size_limit = (repository_size_limit * 1.megabyte) if repository_size_limit.present? + end +end diff --git a/app/models/group.rb b/app/models/group.rb index 7aa6b81d6a81dd..0880e77a8a2064 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -9,6 +9,7 @@ class Group < Namespace include AccessRequestable include Referable include SelectForProjectAuthorization + include RepositorySizeLimit prepend EE::GeoAwareAvatar has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source diff --git a/app/models/project.rb b/app/models/project.rb index d5f1d5cbc92fa9..0c71fd4635e52c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -17,6 +17,7 @@ class Project < ActiveRecord::Base include ProjectFeaturesCompatibility include SelectForProjectAuthorization include Routable + include RepositorySizeLimit prepend EE::GeoAwareAvatar prepend EE::Project diff --git a/spec/models/concerns/repository_size_limit_spec.rb b/spec/models/concerns/repository_size_limit_spec.rb new file mode 100644 index 00000000000000..6dbc591b07af77 --- /dev/null +++ b/spec/models/concerns/repository_size_limit_spec.rb @@ -0,0 +1,91 @@ +require 'spec_helper' + +describe RepositorySizeLimit do + context Project do + context 'callback' do + describe '#convert_from_megabyte_to_byte' do + let(:project) { build(:empty_project, repository_size_limit: 10) } + + before do + project.update!(repository_size_limit: repository_size_limit) + project.reload + end + + context 'when repository_size_limit is present and have changed' do + let(:repository_size_limit) { 20 } + + it { expect(project.repository_size_limit).to eql(20 * 1.megabyte) } + end + + context 'when repository_size_limit is present but have not changed' do + let(:repository_size_limit) { 10 } + + it { expect(project.repository_size_limit).to eql(10 * 1.megabyte) } + end + + context 'when repository_size_limit is not present' do + let(:repository_size_limit) { nil } + + it { expect(project.repository_size_limit).to be_nil } + end + end + end + end + + context Group do + context 'callback' do + describe '#convert_from_megabyte_to_byte' do + let(:group) { build(:group, repository_size_limit: 10) } + + before do + group.update!(repository_size_limit: repository_size_limit) + group.reload + end + + context 'when repository_size_limit is present and have changed' do + let(:repository_size_limit) { 20 } + + it { expect(group.repository_size_limit).to eql(20 * 1.megabyte) } + end + + context 'when repository_size_limit is present but have not changed' do + let(:repository_size_limit) { 10 } + + it { expect(group.repository_size_limit).to eql(10 * 1.megabyte) } + end + + context 'when repository_size_limit is not present' do + let(:repository_size_limit) { nil } + + it { expect(group.repository_size_limit).to be_nil } + end + end + end + end + + context ApplicationSetting do + context 'callback' do + describe '#convert_from_megabyte_to_byte' do + let(:setting) { ApplicationSetting.create_from_defaults } + + before do + setting.update!(repository_size_limit: 10) + setting.update!(repository_size_limit: repository_size_limit) + setting.reload + end + + context 'when repository_size_limit is present and have changed' do + let(:repository_size_limit) { 20 } + + it { expect(setting.repository_size_limit).to eql(20 * 1.megabyte) } + end + + context 'when repository_size_limit is present but have not changed' do + let(:repository_size_limit) { 10 } + + it { expect(setting.repository_size_limit).to eql(10 * 1.megabyte) } + end + end + end + end +end -- GitLab From 3c25eb26b3da546a420802c0f603f4b8a1717bfd Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 19 Jan 2017 16:22:49 -0200 Subject: [PATCH 3/9] Migrate repository size limits from MB to Bytes --- ...settings_repository_size_limit_to_bytes.rb | 42 +++++++++++++++++ ...projects_repository_size_limit_to_bytes.rb | 45 +++++++++++++++++++ ...mespaces_repository_size_limit_to_bytes.rb | 45 +++++++++++++++++++ db/schema.rb | 8 ++-- 4 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb create mode 100644 db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb create mode 100644 db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb diff --git a/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb b/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb new file mode 100644 index 00000000000000..059dda21450381 --- /dev/null +++ b/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb @@ -0,0 +1,42 @@ +class ConvertApplicationSettingsRepositorySizeLimitToBytes < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + disable_ddl_transaction! + + def up + connection.transaction do + rename_column :application_settings, :repository_size_limit, :repository_size_limit_mb + add_column :application_settings, :repository_size_limit, :integer, default: 0, limit: 8 + end + + bigint_expression = if Gitlab::Database.postgresql? + 'repository_size_limit_mb::bigint * 1024 * 1024' + else + 'repository_size_limit_mb * 1024 * 1024' + end + + connection.transaction do + update_column_in_batches(:application_settings, :repository_size_limit, Arel::Nodes::SqlLiteral.new(bigint_expression)) do |t, query| + query.where(t[:repository_size_limit_mb].not_eq(nil)) + end + + remove_column :application_settings, :repository_size_limit_mb + end + end + + def down + connection.transaction do + rename_column :application_settings, :repository_size_limit, :repository_size_limit_bytes + add_column :application_settings, :repository_size_limit, :integer, default: 0, limit: nil + end + + connection.transaction do + update_column_in_batches(:application_settings, :repository_size_limit, Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024')) do |t, query| + query.where(t[:repository_size_limit_bytes].not_eq(nil)) + end + + remove_column :application_settings, :repository_size_limit_bytes + end + end +end diff --git a/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb b/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb new file mode 100644 index 00000000000000..a16ebddf97e903 --- /dev/null +++ b/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb @@ -0,0 +1,45 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class ConvertProjectsRepositorySizeLimitToBytes < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + disable_ddl_transaction! + + def up + connection.transaction do + rename_column :projects, :repository_size_limit, :repository_size_limit_mb + add_column :projects, :repository_size_limit, :integer, limit: 8 + end + + bigint_expression = if Gitlab::Database.postgresql? + 'repository_size_limit_mb::bigint * 1024 * 1024' + else + 'repository_size_limit_mb * 1024 * 1024' + end + + connection.transaction do + update_column_in_batches(:projects, :repository_size_limit, Arel::Nodes::SqlLiteral.new(bigint_expression)) do |t, query| + query.where(t[:repository_size_limit_mb].not_eq(nil)) + end + + remove_column :projects, :repository_size_limit_mb + end + end + + def down + connection.transaction do + rename_column :projects, :repository_size_limit, :repository_size_limit_bytes + add_column :projects, :repository_size_limit, :integer, limit: nil + end + + connection.transaction do + update_column_in_batches(:projects, :repository_size_limit, Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024')) do |t, query| + query.where(t[:repository_size_limit_bytes].not_eq(nil)) + end + + remove_column :projects, :repository_size_limit_bytes + end + end +end diff --git a/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb b/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb new file mode 100644 index 00000000000000..bb358c14f882fb --- /dev/null +++ b/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb @@ -0,0 +1,45 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class ConvertNamespacesRepositorySizeLimitToBytes < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + disable_ddl_transaction! + + def up + connection.transaction do + rename_column :namespaces, :repository_size_limit, :repository_size_limit_mb + add_column :namespaces, :repository_size_limit, :integer, limit: 8 + end + + bigint_expression = if Gitlab::Database.postgresql? + 'repository_size_limit_mb::bigint * 1024 * 1024' + else + 'repository_size_limit_mb * 1024 * 1024' + end + + connection.transaction do + update_column_in_batches(:namespaces, :repository_size_limit, Arel::Nodes::SqlLiteral.new(bigint_expression)) do |t, query| + query.where(t[:repository_size_limit_mb].not_eq(nil)) + end + + remove_column :namespaces, :repository_size_limit_mb + end + end + + def down + connection.transaction do + rename_column :namespaces, :repository_size_limit, :repository_size_limit_bytes + add_column :namespaces, :repository_size_limit, :integer, limit: nil + end + + connection.transaction do + update_column_in_batches(:namespaces, :repository_size_limit, Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024')) do |t, query| + query.where(t[:repository_size_limit_bytes].not_eq(nil)) + end + + remove_column :namespaces, :repository_size_limit_bytes + end + end +end diff --git a/db/schema.rb b/db/schema.rb index d569dd5df02fae..03e962c7f8e95c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170106172237) do +ActiveRecord::Schema.define(version: 20170118200412) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -102,7 +102,6 @@ t.boolean "usage_ping_enabled", default: true, null: false t.boolean "koding_enabled" t.string "koding_url" - t.integer "repository_size_limit", default: 0 t.text "sign_in_text_html" t.text "help_page_text_html" t.text "shared_runners_text_html" @@ -119,6 +118,7 @@ t.string "plantuml_url" t.boolean "plantuml_enabled" t.integer "shared_runners_minutes", default: 0, null: false + t.integer "repository_size_limit", limit: 8, default: 0 end create_table "approvals", force: :cascade do |t| @@ -853,10 +853,10 @@ t.datetime "ldap_sync_last_sync_at" t.datetime "deleted_at" t.boolean "lfs_enabled" - t.integer "repository_size_limit" t.text "description_html" t.integer "parent_id" t.integer "shared_runners_minutes_limit" + t.integer "repository_size_limit", limit: 8 end add_index "namespaces", ["created_at"], name: "index_namespaces_on_created_at", using: :btree @@ -1105,8 +1105,8 @@ t.boolean "repository_read_only" t.boolean "lfs_enabled" t.text "description_html" - t.integer "repository_size_limit" t.boolean "only_allow_merge_if_all_discussions_are_resolved" + t.integer "repository_size_limit", limit: 8 end add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree -- GitLab From 2a2e91f9df9ff4852e68a49c4ad9ab525f518605 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 19 Jan 2017 16:23:43 -0200 Subject: [PATCH 4/9] Show repository size limit as MB to the user --- app/views/admin/application_settings/_form.html.haml | 2 +- app/views/groups/_repository_size_limit_setting.html.haml | 2 +- app/views/projects/edit.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 85b451da131292..d771c3e6443d44 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -67,7 +67,7 @@ = f.label :repository_size_limit, class: 'control-label col-sm-2' do Size limit per repository (MB) .col-sm-10 - = f.number_field :repository_size_limit, class: 'form-control', min: 0 + = f.number_field :repository_size_limit, value: f.object.repository_size_limit.try(:to_mb), class: 'form-control', min: 0 %span.help-block#repository_size_limit_help_block Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited. = link_to icon('question-circle'), help_page_path("user/admin_area/settings/account_and_limit_settings") diff --git a/app/views/groups/_repository_size_limit_setting.html.haml b/app/views/groups/_repository_size_limit_setting.html.haml index 27463737489985..7d36627243b25b 100644 --- a/app/views/groups/_repository_size_limit_setting.html.haml +++ b/app/views/groups/_repository_size_limit_setting.html.haml @@ -3,6 +3,6 @@ = f.label :repository_size_limit, class: 'control-label' do Repository size limit (MB) .col-sm-10 - = f.number_field :repository_size_limit, class: 'form-control', min: 0 + = f.number_field :repository_size_limit, value: f.object.repository_size_limit.try(:to_mb), class: 'form-control', min: 0 %span.help-block#repository_size_limit_help_block = size_limit_message_for_group(@group) diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 680eac0fa0693d..ed608f111eec70 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -38,7 +38,7 @@ .form-group = f.label :repository_size_limit, class: 'label-light' do Repository size limit (MB) - = f.number_field :repository_size_limit, class: 'form-control', min: 0 + = f.number_field :repository_size_limit, value: f.object.repository_size_limit.try(:to_mb), class: 'form-control', min: 0 %span.help-block#repository_size_limit_help_block = size_limit_message(@project) -- GitLab From 18c3f93bf351db48271acbeba46efc822b730108 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 19 Jan 2017 16:24:33 -0200 Subject: [PATCH 5/9] Ensure column can hold 8 byte values --- spec/models/application_setting_spec.rb | 10 ++++++++++ spec/models/ee/group_spec.rb | 13 ++++++++++++- spec/models/project_spec.rb | 11 +++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index b950fcdd81aae0..7fab73500c313f 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -176,4 +176,14 @@ expect(setting.domain_blacklist).to contain_exactly('example.com', 'test.com', 'foo.bar') end end + + describe '#repository_size_limit column' do + it 'support values up to 8 exabytes' do + setting.update_column(:repository_size_limit, 8.exabytes - 1) + + setting.reload + + expect(setting.repository_size_limit).to eql(8.exabytes - 1) + end + end end diff --git a/spec/models/ee/group_spec.rb b/spec/models/ee/group_spec.rb index 62d3bdbcd89681..287953ac0411c5 100644 --- a/spec/models/ee/group_spec.rb +++ b/spec/models/ee/group_spec.rb @@ -100,7 +100,18 @@ it 'returns the value set locally' do group.update_attribute(:repository_size_limit, 75) - expect(group.actual_size_limit).to eq(75) + expect(group.actual_size_limit).to eq(75.megabytes) + end + end + + describe '#repository_size_limit column' do + it 'support values up to 8 exabytes' do + group = create(:group) + group.update_column(:repository_size_limit, 8.exabytes - 1) + + group.reload + + expect(group.repository_size_limit).to eql(8.exabytes - 1) end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 810f38372224d6..b91150664292ec 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -623,6 +623,17 @@ end end + describe '#repository_size_limit column' do + it 'support values up to 8 exabytes' do + project = create(:empty_project) + project.update_column(:repository_size_limit, 8.exabytes - 1) + + project.reload + + expect(project.repository_size_limit).to eql(8.exabytes - 1) + end + end + describe '#default_issues_tracker?' do it "is true if used internal tracker" do project = build(:empty_project) -- GitLab From 01e551fe8018412883a8f01466f5fd4144e1014a Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Fri, 20 Jan 2017 10:14:54 -0200 Subject: [PATCH 6/9] Remove size limit convertion concern --- app/models/application_setting.rb | 1 - app/models/concerns/repository_size_limit.rb | 13 --- app/models/group.rb | 1 - app/models/project.rb | 1 - .../concerns/repository_size_limit_spec.rb | 91 ------------------- 5 files changed, 107 deletions(-) delete mode 100644 app/models/concerns/repository_size_limit.rb delete mode 100644 spec/models/concerns/repository_size_limit_spec.rb diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index d38a2f810dbfee..d76f7481569d15 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -2,7 +2,6 @@ class ApplicationSetting < ActiveRecord::Base include CacheMarkdownField include TokenAuthenticatable prepend EE::ApplicationSetting - include RepositorySizeLimit add_authentication_token_field :runners_registration_token add_authentication_token_field :health_check_access_token diff --git a/app/models/concerns/repository_size_limit.rb b/app/models/concerns/repository_size_limit.rb deleted file mode 100644 index b80dda3d88cd10..00000000000000 --- a/app/models/concerns/repository_size_limit.rb +++ /dev/null @@ -1,13 +0,0 @@ -module RepositorySizeLimit - extend ActiveSupport::Concern - - included do - before_save :convert_from_megabytes_to_bytes, if: :repository_size_limit_changed? - end - - private - - def convert_from_megabytes_to_bytes - self.repository_size_limit = (repository_size_limit * 1.megabyte) if repository_size_limit.present? - end -end diff --git a/app/models/group.rb b/app/models/group.rb index 0880e77a8a2064..7aa6b81d6a81dd 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -9,7 +9,6 @@ class Group < Namespace include AccessRequestable include Referable include SelectForProjectAuthorization - include RepositorySizeLimit prepend EE::GeoAwareAvatar has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source diff --git a/app/models/project.rb b/app/models/project.rb index 0c71fd4635e52c..d5f1d5cbc92fa9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -17,7 +17,6 @@ class Project < ActiveRecord::Base include ProjectFeaturesCompatibility include SelectForProjectAuthorization include Routable - include RepositorySizeLimit prepend EE::GeoAwareAvatar prepend EE::Project diff --git a/spec/models/concerns/repository_size_limit_spec.rb b/spec/models/concerns/repository_size_limit_spec.rb deleted file mode 100644 index 6dbc591b07af77..00000000000000 --- a/spec/models/concerns/repository_size_limit_spec.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'spec_helper' - -describe RepositorySizeLimit do - context Project do - context 'callback' do - describe '#convert_from_megabyte_to_byte' do - let(:project) { build(:empty_project, repository_size_limit: 10) } - - before do - project.update!(repository_size_limit: repository_size_limit) - project.reload - end - - context 'when repository_size_limit is present and have changed' do - let(:repository_size_limit) { 20 } - - it { expect(project.repository_size_limit).to eql(20 * 1.megabyte) } - end - - context 'when repository_size_limit is present but have not changed' do - let(:repository_size_limit) { 10 } - - it { expect(project.repository_size_limit).to eql(10 * 1.megabyte) } - end - - context 'when repository_size_limit is not present' do - let(:repository_size_limit) { nil } - - it { expect(project.repository_size_limit).to be_nil } - end - end - end - end - - context Group do - context 'callback' do - describe '#convert_from_megabyte_to_byte' do - let(:group) { build(:group, repository_size_limit: 10) } - - before do - group.update!(repository_size_limit: repository_size_limit) - group.reload - end - - context 'when repository_size_limit is present and have changed' do - let(:repository_size_limit) { 20 } - - it { expect(group.repository_size_limit).to eql(20 * 1.megabyte) } - end - - context 'when repository_size_limit is present but have not changed' do - let(:repository_size_limit) { 10 } - - it { expect(group.repository_size_limit).to eql(10 * 1.megabyte) } - end - - context 'when repository_size_limit is not present' do - let(:repository_size_limit) { nil } - - it { expect(group.repository_size_limit).to be_nil } - end - end - end - end - - context ApplicationSetting do - context 'callback' do - describe '#convert_from_megabyte_to_byte' do - let(:setting) { ApplicationSetting.create_from_defaults } - - before do - setting.update!(repository_size_limit: 10) - setting.update!(repository_size_limit: repository_size_limit) - setting.reload - end - - context 'when repository_size_limit is present and have changed' do - let(:repository_size_limit) { 20 } - - it { expect(setting.repository_size_limit).to eql(20 * 1.megabyte) } - end - - context 'when repository_size_limit is present but have not changed' do - let(:repository_size_limit) { 10 } - - it { expect(setting.repository_size_limit).to eql(10 * 1.megabyte) } - end - end - end - end -end -- GitLab From 574b9c6771170ccaf7f0323492ce67a5900acb39 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Fri, 20 Jan 2017 11:42:38 -0200 Subject: [PATCH 7/9] Address MB to Bytes convertion on update/create services --- .../admin/application_settings_controller.rb | 4 +- .../application_settings/base_service.rb | 9 +++ .../application_settings/create_service.rb | 0 .../application_settings/update_service.rb | 14 ++++ app/services/base_service.rb | 7 ++ app/services/groups/create_service.rb | 3 + app/services/groups/update_service.rb | 3 + app/services/projects/create_service.rb | 3 + app/services/projects/update_service.rb | 3 + .../application_settings_controller_spec.rb | 30 ++++++++ spec/models/ee/group_spec.rb | 2 +- spec/models/project_spec.rb | 4 +- .../update_service_spec.rb | 69 +++++++++++++++++++ spec/services/groups/create_service_spec.rb | 25 +++++++ spec/services/groups/update_service_spec.rb | 25 +++++++ spec/services/projects/create_service_spec.rb | 24 +++++++ spec/services/projects/update_service_spec.rb | 25 +++++++ 17 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 app/services/application_settings/base_service.rb create mode 100644 app/services/application_settings/create_service.rb create mode 100644 app/services/application_settings/update_service.rb create mode 100644 spec/services/application_settings/update_service_spec.rb diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index c977f42858d9c6..c3ad7394e4e587 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -5,7 +5,9 @@ def show end def update - if @application_setting.update_attributes(application_setting_params) + result = ::ApplicationSettings::UpdateService.new(@application_setting, current_user, application_setting_params).execute + + if result[:status] == :success redirect_to admin_application_settings_path, notice: 'Application settings saved successfully' else diff --git a/app/services/application_settings/base_service.rb b/app/services/application_settings/base_service.rb new file mode 100644 index 00000000000000..d452718491bda3 --- /dev/null +++ b/app/services/application_settings/base_service.rb @@ -0,0 +1,9 @@ +module ApplicationSettings + class BaseService < ::BaseService + attr_accessor :application_setting, :current_user, :params + + def initialize(application_setting, user, params = {}) + @application_setting, @current_user, @params = application_setting, user, params.dup + end + end +end diff --git a/app/services/application_settings/create_service.rb b/app/services/application_settings/create_service.rb new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb new file mode 100644 index 00000000000000..521aa37c9ea5ff --- /dev/null +++ b/app/services/application_settings/update_service.rb @@ -0,0 +1,14 @@ +module ApplicationSettings + class UpdateService < ApplicationSettings::BaseService + def execute + # Repository size limit comes as MB from the view + assign_repository_size_limit_as_bytes(application_setting) + + if application_setting.update(params) + success + else + error('Application settings could not be updated') + end + end + end +end diff --git a/app/services/base_service.rb b/app/services/base_service.rb index 1a2bad77a0291e..9d333fa3f5aa76 100644 --- a/app/services/base_service.rb +++ b/app/services/base_service.rb @@ -46,6 +46,13 @@ def deny_visibility_level(model, denied_visibility_level = nil) private + def assign_repository_size_limit_as_bytes(model) + repository_size_limit = @params.delete(:repository_size_limit) + new_value = repository_size_limit.to_i.megabytes if repository_size_limit.present? + + model.repository_size_limit = new_value + end + def error(message, http_status = nil) result = { message: message, diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb index febeb661fb5f3b..ec621a6b06409e 100644 --- a/app/services/groups/create_service.rb +++ b/app/services/groups/create_service.rb @@ -12,6 +12,9 @@ def execute return @group end + # Repository size limit comes as MB from the view + assign_repository_size_limit_as_bytes(@group) + if @group.parent && !can?(current_user, :admin_group, @group.parent) @group.parent = nil @group.errors.add(:parent_id, 'manage access required to create subgroup') diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb index 4e878ec556a2e7..c8eff0f4c75175 100644 --- a/app/services/groups/update_service.rb +++ b/app/services/groups/update_service.rb @@ -12,6 +12,9 @@ def execute end end + # Repository size limit comes as MB from the view + assign_repository_size_limit_as_bytes(group) + group.assign_attributes(params) begin diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 31e3902d86f3a3..642a899d89736e 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -22,6 +22,9 @@ def execute return @project end + # Repository size limit comes as MB from the view + assign_repository_size_limit_as_bytes(@project) + # Set project name from path if @project.name.present? && @project.path.present? # if both name and path set - everything is ok diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 955b69258a10e3..6edff7c5352571 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -13,6 +13,9 @@ def execute end end + # Repository size limit comes as MB from the view + assign_repository_size_limit_as_bytes(project) + new_branch = params.delete(:default_branch) new_repository_storage = params.delete(:repository_storage) diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index 763de76d453ddc..bab8a03feec25f 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -6,6 +6,36 @@ let(:admin) { create(:admin) } let(:user) { create(:user)} + describe 'PUT #update' do + before do + sign_in(admin) + end + + context 'with valid params' do + subject { put :update, application_setting: { repository_size_limit: '100' } } + + it 'redirect to application settings page' do + is_expected.to redirect_to(admin_application_settings_path) + end + + it 'set flash notice' do + is_expected.to set_flash[:notice].to('Application settings saved successfully') + end + end + + context 'with invalid params' do + subject! { put :update, application_setting: { repository_size_limit: '-100' } } + + it 'render show template' do + is_expected.to render_template(:show) + end + + it 'assigned @application_settings has errors' do + expect(assigns(:application_setting).errors[:repository_size_limit]).to be_present + end + end + end + describe 'GET #usage_data with no access' do before do sign_in(user) diff --git a/spec/models/ee/group_spec.rb b/spec/models/ee/group_spec.rb index 287953ac0411c5..816efa3e0ff85b 100644 --- a/spec/models/ee/group_spec.rb +++ b/spec/models/ee/group_spec.rb @@ -100,7 +100,7 @@ it 'returns the value set locally' do group.update_attribute(:repository_size_limit, 75) - expect(group.actual_size_limit).to eq(75.megabytes) + expect(group.actual_size_limit).to eq(75) end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index b91150664292ec..03713a79993031 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -573,13 +573,13 @@ group = create(:group, repository_size_limit: 100) project.update_attribute(:namespace_id, group.id) - expect(project.actual_size_limit).to eq(100.megabytes) + expect(project.actual_size_limit).to eq(100) end it 'returns the value set locally' do project.update_attribute(:repository_size_limit, 75) - expect(project.actual_size_limit).to eq(75.megabytes) + expect(project.actual_size_limit).to eq(75) end end diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb new file mode 100644 index 00000000000000..6ec51b65318a6c --- /dev/null +++ b/spec/services/application_settings/update_service_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +describe ApplicationSettings::UpdateService, services: true do + let(:user) { create(:user) } + let(:setting) { ApplicationSetting.create_from_defaults } + let(:service) { described_class.new(setting, user, opts) } + + describe '#execute' do + context 'common params' do + let(:opts) { { home_page_url: 'http://foo.bar' } } + + it 'properly updates settings with given params' do + service.execute + + expect(setting.home_page_url).to eql(opts[:home_page_url]) + end + end + + context 'with valid params' do + let(:opts) { { repository_size_limit: '100' } } + + it 'returns success params' do + result = service.execute + + expect(result).to eql(status: :success) + end + end + + context 'with invalid params' do + let(:opts) { { repository_size_limit: '-100' } } + + it 'returns error params' do + result = service.execute + + expect(result).to eql(message: "Application settings could not be updated", status: :error) + end + end + + context 'repository_size_limit assignment as Bytes' do + let(:service) { described_class.new(setting, user, opts) } + + context 'when param present' do + let(:opts) { { repository_size_limit: '100' } } + + it 'converts from MB to Bytes' do + service.execute + + expect(setting.reload.repository_size_limit).to eql(100 * 1024 * 1024) + end + end + + context 'when param not present' do + let(:opts) { { repository_size_limit: '' } } + + it 'does not update due to invalidity' do + service.execute + + expect(setting.reload.repository_size_limit).to be_zero + end + + it 'assign nil value' do + service.execute + + expect(setting.repository_size_limit).to be_nil + end + end + end + end +end diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb index 14717a7455d3de..116219475500f3 100644 --- a/spec/services/groups/create_service_spec.rb +++ b/spec/services/groups/create_service_spec.rb @@ -40,4 +40,29 @@ end end end + + context 'repository_size_limit assignment as Bytes' do + let(:admin_user) { create(:user, admin: true) } + let(:service) { described_class.new(admin_user, group_params.merge(opts)) } + + context 'when param present' do + let(:opts) { { repository_size_limit: '100' } } + + it 'assign repository_size_limit as Bytes' do + group = service.execute + + expect(group.repository_size_limit).to eql(100 * 1024 * 1024) + end + end + + context 'when param not present' do + let(:opts) { { repository_size_limit: '' } } + + it 'assign nil value' do + group = service.execute + + expect(group.repository_size_limit).to be_nil + end + end + end end diff --git a/spec/services/groups/update_service_spec.rb b/spec/services/groups/update_service_spec.rb index 531180e48a1db0..4a045b78187b3f 100644 --- a/spec/services/groups/update_service_spec.rb +++ b/spec/services/groups/update_service_spec.rb @@ -38,6 +38,31 @@ end end + context 'repository_size_limit assignment as Bytes' do + let(:group) { create(:group, :public, repository_size_limit: 0) } + let(:service) { described_class.new(group, user, opts) } + + context 'when param present' do + let(:opts) { { repository_size_limit: '100' } } + + it 'converts from MB to Bytes' do + service.execute + + expect(group.reload.repository_size_limit).to eql(100 * 1024 * 1024) + end + end + + context 'when param not present' do + let(:opts) { { repository_size_limit: '' } } + + it 'assign nil value' do + service.execute + + expect(group.reload.repository_size_limit).to be_nil + end + end + end + context "unauthorized visibility_level validation" do let!(:service) { described_class.new(internal_group, user, visibility_level: 99) } before do diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 466e18fbe00933..d75d913c2bff0b 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -98,6 +98,30 @@ end end + context 'repository_size_limit assignment as Bytes' do + let(:admin_user) { create(:user, admin: true) } + + context 'when param present' do + let(:opts) { { repository_size_limit: '100' } } + + it 'assign repository_size_limit as Bytes' do + project = create_project(admin_user, opts) + + expect(project.repository_size_limit).to eql(100 * 1024 * 1024) + end + end + + context 'when param not present' do + let(:opts) { { repository_size_limit: '' } } + + it 'assign nil value' do + project = create_project(admin_user, opts) + + expect(project.repository_size_limit).to be_nil + end + end + end + context 'restricted visibility level' do before do stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index 9de7d64409c4ae..13397e2b6ca1ff 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -127,6 +127,31 @@ end end + context 'repository_size_limit assignment as Bytes' do + let(:admin_user) { create(:user, admin: true) } + let(:project) { create(:empty_project, repository_size_limit: 0) } + + context 'when param present' do + let(:opts) { { repository_size_limit: '100' } } + + it 'converts from MB to Bytes' do + update_project(project, admin_user, opts) + + expect(project.reload.repository_size_limit).to eql(100 * 1024 * 1024) + end + end + + context 'when param not present' do + let(:opts) { { repository_size_limit: '' } } + + it 'assign nil value' do + update_project(project, admin_user, opts) + + expect(project.reload.repository_size_limit).to be_nil + end + end + end + it 'returns an error result when record cannot be updated' do result = update_project(project, admin, { name: 'foo&bar' }) -- GitLab From 343e42b68769406508ebaadd1347e43e810278f8 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Fri, 20 Jan 2017 12:07:08 -0200 Subject: [PATCH 8/9] Improve migrations readability --- ..._settings_repository_size_limit_to_bytes.rb | 18 +++++++++++------- ..._projects_repository_size_limit_to_bytes.rb | 18 +++++++++++------- ...amespaces_repository_size_limit_to_bytes.rb | 18 +++++++++++------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb b/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb index 059dda21450381..1cee31aa595b80 100644 --- a/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb +++ b/db/migrate/20170118194941_convert_application_settings_repository_size_limit_to_bytes.rb @@ -10,14 +10,16 @@ def up add_column :application_settings, :repository_size_limit, :integer, default: 0, limit: 8 end - bigint_expression = if Gitlab::Database.postgresql? - 'repository_size_limit_mb::bigint * 1024 * 1024' - else - 'repository_size_limit_mb * 1024 * 1024' - end + bigint_string = if Gitlab::Database.postgresql? + 'repository_size_limit_mb::bigint * 1024 * 1024' + else + 'repository_size_limit_mb * 1024 * 1024' + end + + sql_expression = Arel::Nodes::SqlLiteral.new(bigint_string) connection.transaction do - update_column_in_batches(:application_settings, :repository_size_limit, Arel::Nodes::SqlLiteral.new(bigint_expression)) do |t, query| + update_column_in_batches(:application_settings, :repository_size_limit, sql_expression) do |t, query| query.where(t[:repository_size_limit_mb].not_eq(nil)) end @@ -31,8 +33,10 @@ def down add_column :application_settings, :repository_size_limit, :integer, default: 0, limit: nil end + sql_expression = Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024') + connection.transaction do - update_column_in_batches(:application_settings, :repository_size_limit, Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024')) do |t, query| + update_column_in_batches(:application_settings, :repository_size_limit, sql_expression) do |t, query| query.where(t[:repository_size_limit_bytes].not_eq(nil)) end diff --git a/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb b/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb index a16ebddf97e903..043ca5c384f0a4 100644 --- a/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb +++ b/db/migrate/20170118200338_convert_projects_repository_size_limit_to_bytes.rb @@ -13,14 +13,16 @@ def up add_column :projects, :repository_size_limit, :integer, limit: 8 end - bigint_expression = if Gitlab::Database.postgresql? - 'repository_size_limit_mb::bigint * 1024 * 1024' - else - 'repository_size_limit_mb * 1024 * 1024' - end + bigint_string = if Gitlab::Database.postgresql? + 'repository_size_limit_mb::bigint * 1024 * 1024' + else + 'repository_size_limit_mb * 1024 * 1024' + end + + sql_expression = Arel::Nodes::SqlLiteral.new(bigint_string) connection.transaction do - update_column_in_batches(:projects, :repository_size_limit, Arel::Nodes::SqlLiteral.new(bigint_expression)) do |t, query| + update_column_in_batches(:projects, :repository_size_limit, sql_expression) do |t, query| query.where(t[:repository_size_limit_mb].not_eq(nil)) end @@ -34,8 +36,10 @@ def down add_column :projects, :repository_size_limit, :integer, limit: nil end + sql_expression = Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024') + connection.transaction do - update_column_in_batches(:projects, :repository_size_limit, Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024')) do |t, query| + update_column_in_batches(:projects, :repository_size_limit, sql_expression) do |t, query| query.where(t[:repository_size_limit_bytes].not_eq(nil)) end diff --git a/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb b/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb index bb358c14f882fb..d7b597aa276de5 100644 --- a/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb +++ b/db/migrate/20170118200412_convert_namespaces_repository_size_limit_to_bytes.rb @@ -13,14 +13,16 @@ def up add_column :namespaces, :repository_size_limit, :integer, limit: 8 end - bigint_expression = if Gitlab::Database.postgresql? - 'repository_size_limit_mb::bigint * 1024 * 1024' - else - 'repository_size_limit_mb * 1024 * 1024' - end + bigint_string = if Gitlab::Database.postgresql? + 'repository_size_limit_mb::bigint * 1024 * 1024' + else + 'repository_size_limit_mb * 1024 * 1024' + end + + sql_expression = Arel::Nodes::SqlLiteral.new(bigint_string) connection.transaction do - update_column_in_batches(:namespaces, :repository_size_limit, Arel::Nodes::SqlLiteral.new(bigint_expression)) do |t, query| + update_column_in_batches(:namespaces, :repository_size_limit, sql_expression) do |t, query| query.where(t[:repository_size_limit_mb].not_eq(nil)) end @@ -34,8 +36,10 @@ def down add_column :namespaces, :repository_size_limit, :integer, limit: nil end + sql_expression = Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024') + connection.transaction do - update_column_in_batches(:namespaces, :repository_size_limit, Arel::Nodes::SqlLiteral.new('repository_size_limit_bytes / 1024 / 1024')) do |t, query| + update_column_in_batches(:namespaces, :repository_size_limit, sql_expression) do |t, query| query.where(t[:repository_size_limit_bytes].not_eq(nil)) end -- GitLab From 1b902a99094df14445c7f03e7b50e9e952f521a1 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Fri, 20 Jan 2017 15:15:52 -0200 Subject: [PATCH 9/9] Adjust spec with wrong limit value (MBs) --- spec/lib/gitlab/git_access_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 52128583dbda06..97cfcf6e078cbe 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -751,7 +751,7 @@ def self.run_group_permission_checks(permissions_matrix) describe 'repository size restrictions' do before do - project.update_attribute(:repository_size_limit, 50) + project.update_attribute(:repository_size_limit, 50.megabytes) end it 'returns false when blob is too big' do -- GitLab