diff --git a/modules/bim/app/controllers/bim/ifc_models/ifc_models_controller.rb b/modules/bim/app/controllers/bim/ifc_models/ifc_models_controller.rb index 6c64972e7752..00c6bdcca400 100644 --- a/modules/bim/app/controllers/bim/ifc_models/ifc_models_controller.rb +++ b/modules/bim/app/controllers/bim/ifc_models/ifc_models_controller.rb @@ -65,6 +65,13 @@ def defaults end def set_direct_upload_file_name + if params[:filesize].to_i > Setting.attachment_max_size.to_i.kilobytes + render json: { error: I18n.t("activerecord.errors.messages.file_too_large", + count: Setting.attachment_max_size.to_i.kilobytes) }, + status: :unprocessable_entity + return + end + session[:pending_ifc_model_title] = params[:title] session[:pending_ifc_model_is_default] = params[:isDefault] end diff --git a/modules/bim/app/views/bim/ifc_models/ifc_models/_form.html.erb b/modules/bim/app/views/bim/ifc_models/ifc_models/_form.html.erb index 62d8e3464db2..20ee195c3837 100644 --- a/modules/bim/app/views/bim/ifc_models/ifc_models/_form.html.erb +++ b/modules/bim/app/views/bim/ifc_models/ifc_models/_form.html.erb @@ -62,6 +62,10 @@ See COPYRIGHT and LICENSE files for more details. fileName = fileNameField[0].files[0].name; } + <%# Reset the form validity %> + <%# See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity %> + fileNameField[0].setCustomValidity(''); + var titleField = jQuery("#bim_ifc_models_ifc_model_title"); <%# When creating a new model, there is no titleField. %> @@ -86,12 +90,20 @@ See COPYRIGHT and LICENSE files for more details. }, data: { title: title, - isDefault: jQuery("#bim_ifc_models_ifc_model_is_default").is(":checked") ? 1 : 0 + isDefault: jQuery("#bim_ifc_models_ifc_model_is_default").is(":checked") ? 1 : 0, + filesize: fileNameField[0].files[0].size }, statusCode: { 401: function(resp, status, error) { document.location.reload(); // reload to make user login again } + }, + error: function(jqXHR, ajaxOptions, errorThrown) { + if (jqXHR.status == 422) { + var errorMessage = jqXHR.responseJSON.error; + fileNameField[0].setCustomValidity(errorMessage); + fileNameField[0].reportValidity(); + } } }); }; diff --git a/modules/bim/spec/features/ifc_models/direct_ifc_upload_spec.rb b/modules/bim/spec/features/ifc_models/direct_ifc_upload_spec.rb index f6e7a9c0be22..6058222ffa85 100644 --- a/modules/bim/spec/features/ifc_models/direct_ifc_upload_spec.rb +++ b/modules/bim/spec/features/ifc_models/direct_ifc_upload_spec.rb @@ -33,5 +33,23 @@ it_behaves_like "can upload an IFC file" do # with direct upload, we don't get the model name let(:model_name) { "model.ifc" } + + context "when the file size exceeds the allowed maximum", with_settings: { attachment_max_size: 1 } do + it "invalidates the form via JavaScript preventing submission" do + pending "This test is currently flaky due to an unknown reason" + + visit new_bcf_project_ifc_model_path(project_id: project.identifier) + + page.attach_file("file", ifc_fixture.path, visible: :all) + + form_validity = page.evaluate_script <<~JS + document + .querySelector('#new_bim_ifc_models_ifc_model') + .checkValidity(); + JS + + expect(form_validity).to be(false) + end + end end end diff --git a/modules/bim/spec/features/ifc_models/regular_ifc_upload_spec.rb b/modules/bim/spec/features/ifc_models/regular_ifc_upload_spec.rb index e9ceec4c3ecc..a7b6678e3205 100644 --- a/modules/bim/spec/features/ifc_models/regular_ifc_upload_spec.rb +++ b/modules/bim/spec/features/ifc_models/regular_ifc_upload_spec.rb @@ -32,5 +32,17 @@ RSpec.describe "IFC upload", :js, with_config: { edition: "bim" } do it_behaves_like "can upload an IFC file" do let(:model_name) { "minimal.ifc" } + + context "when the file size exceeds the allowed maximum", with_settings: { attachment_max_size: 1 } do + it "renders an error message" do + visit new_bcf_project_ifc_model_path(project_id: project.identifier) + + page.attach_file("file", ifc_fixture.path, visible: :all) + + click_on "Create" + + expect(page).to have_content("IFC file is too large (maximum size is 1024 Bytes).") + end + end end end diff --git a/modules/bim/spec/requests/ifc_models/set_direct_upload_filename_spec.rb b/modules/bim/spec/requests/ifc_models/set_direct_upload_filename_spec.rb new file mode 100644 index 000000000000..99f468207fa0 --- /dev/null +++ b/modules/bim/spec/requests/ifc_models/set_direct_upload_filename_spec.rb @@ -0,0 +1,55 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" +require_module_spec_helper + +RSpec.describe "POST /projects/:project_id/ifc_models/set_direct_upload_file_name" do + shared_let(:user) { create(:admin, preferences: { time_zone: "Etc/UTC" }) } + let(:project) { build_stubbed(:project) } + + context "when user is not logged in" do + it "requires login" do + post set_direct_upload_file_name_bcf_project_ifc_models_path(project_id: project.id) + expect(last_response.status).to eq(406) # rubocop:disable RSpecRails/HaveHttpStatus + end + end + + context "when user is logged in" do + before { login_as(user) } + + context "and the upload exceeds the maximum size", with_settings: { attachment_max_size: 1 } do + it "returns a 422" do + post set_direct_upload_file_name_bcf_project_ifc_models_path(project_id: project.id), + { title: "Test.ifc", isDefault: "0", filesize: "113328073" } + expect(last_response.status).to eq(422) # rubocop:disable RSpecRails/HaveHttpStatus + expect(parse_json(last_response.body)).to eq({ "error" => "is too large (maximum size is 1024 Bytes)." }) + end + end + end +end