From 9fc974af206db2414a8cedc2d812a342a076ad50 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Tue, 10 May 2016 16:03:52 +0200 Subject: [PATCH] Implement file name validation based on path, name, and filetype upon file creation --- app/controllers/code_ocean/files_controller.rb | 15 +++++++++++++++ app/models/code_ocean/file.rb | 13 +++++++++++++ config/locales/de.yml | 2 ++ config/locales/en.yml | 2 ++ 4 files changed, 32 insertions(+) diff --git a/app/controllers/code_ocean/files_controller.rb b/app/controllers/code_ocean/files_controller.rb index 3c255ffa..74c1932f 100644 --- a/app/controllers/code_ocean/files_controller.rb +++ b/app/controllers/code_ocean/files_controller.rb @@ -14,6 +14,21 @@ module CodeOcean create_and_respond(object: @file, path: proc { implement_exercise_path(@file.context.exercise, tab: 2) }) end + def create_and_respond(options = {}) + @object = options[:object] + respond_to do |format| + if @object.save + yield if block_given? + path = options[:path].try(:call) || @object + respond_with_valid_object(format, notice: t('shared.object_created', model: @object.class.model_name.human), path: path, status: :created) + else + filename = (@object.path || '') + '/' + (@object.name || '') + (@object.file_type.file_extension || '') + format.html { redirect_to(options[:path]); flash[:danger] = t('files.error.filename', name: filename) } + format.json { render(json: @object.errors, status: :unprocessable_entity) } + end + end + end + def destroy @file = CodeOcean::File.find(params[:id]) authorize! diff --git a/app/models/code_ocean/file.rb b/app/models/code_ocean/file.rb index 48ec97d0..7b00cbdd 100644 --- a/app/models/code_ocean/file.rb +++ b/app/models/code_ocean/file.rb @@ -2,6 +2,17 @@ require File.expand_path('../../../uploaders/file_uploader', __FILE__) require File.expand_path('../../../../lib/active_model/validations/boolean_presence_validator', __FILE__) module CodeOcean + + class FileNameValidator < ActiveModel::Validator + def validate(record) + existing_files = File.where(name: record.name, path: record.path, file_type_id: record.file_type_id, + context_id: record.context_id, context: record.context).to_a + unless existing_files.empty? + record.errors[:base] << 'Duplicate' + end + end + end + class File < ActiveRecord::Base include DefaultValues @@ -44,6 +55,8 @@ module CodeOcean validates :weight, if: :teacher_defined_test?, numericality: true, presence: true validates :weight, absence: true, unless: :teacher_defined_test? + validates_with FileNameValidator, fields: [:name, :path, :file_type_id] + ROLES.each do |role| define_method("#{role}?") { self.role == role } end diff --git a/config/locales/de.yml b/config/locales/de.yml index ddc6bfa4..ed66f79a 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -292,6 +292,8 @@ de: teacher_defined_test: Test als Bewertungsgrundlage user_defined_file: Benutzerdefinierte Datei user_defined_test: Benutzerdefinierter Test + error: + filename: "Die Datei konnte nicht gespeichert werden, da eine Datei mit dem Namen '%{name}' bereits existiert." hints: form: hints: diff --git a/config/locales/en.yml b/config/locales/en.yml index f083f5f9..f86a6963 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -292,6 +292,8 @@ en: teacher_defined_test: Test for Assessment user_defined_file: User-defined File user_defined_test: User-defined Test + error: + filename: "The file could not be saved, because another file with the name '%{name}' already exists." hints: form: hints: