1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-19 13:54:25 +01:00

test mime type of a file

use marcel to test mime types
updated mimemagic
This commit is contained in:
Sylvain 2020-06-03 16:25:13 +02:00
parent 743f3e510a
commit 5c152412db
13 changed files with 127 additions and 35 deletions

View File

@ -236,7 +236,7 @@ GEM
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2020.0512)
mimemagic (0.3.4)
mimemagic (0.3.5)
mini_magick (4.10.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)

View File

@ -12,8 +12,8 @@
*/
'use strict';
Application.Controllers.controller('AdminProjectsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise', '_t', 'Member', 'uiTourService', 'settingsPromise',
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise, _t, Member, uiTourService, settingsPromise) {
Application.Controllers.controller('AdminProjectsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise', '_t', 'Member', 'uiTourService', 'settingsPromise', 'growl',
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise, _t, Member, uiTourService, settingsPromise, growl) {
// Materials list (plastic, wood ...)
$scope.components = componentsPromise;
@ -158,6 +158,30 @@ Application.Controllers.controller('AdminProjectsController', ['$scope', '$state
}
};
/**
* When a file is sent to the server to test it against its MIME type,
* handle the result of the test.
*/
$scope.onTestFileComplete = function (res) {
if (res) {
growl.success(_t('app.admin.projects.settings.file_is_TYPE', { TYPE: res.type }));
}
};
/**
* For use with 'ng-class', returns the CSS class name for the uploads previews.
* The preview may show a placeholder or the content of the file depending on the upload state.
* @param v {*} any attribute, will be tested for truthiness (see JS evaluation rules)
*/
$scope.fileinputClass = function (v) {
if (v) {
return 'fileinput-exists';
} else {
return 'fileinput-new';
}
};
/**
* Setup the feature-tour for the admin/projects page.
* This is intended as a contextual help (when pressing F1)

View File

@ -314,29 +314,6 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
$scope.codeMirrorEditor = editor;
}
/**
* Assign the current URL to the settings ( base_url_protocol & base_url_host )
* and save them to teh database.
*/
$scope.detectFillUrl = function () {
$scope.allSettings.base_url_protocol = window.location.protocol.match(/^([a-z]+):?$/)[1]
$scope.allSettings.base_url_host = window.location.host;
Setting.bulkUpdate(
{
settings: [
{ name: 'base_url_protocol', value: $scope.allSettings.base_url_protocol } ,
{ name: 'base_url_host', value: $scope.allSettings.base_url_host }
]
},
function () { growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.base_url`) })); },
function (error) {
growl.error('app.admin.settings.an_error_occurred_saving_the_setting');
console.error(error);
}
);
}
/**
* Setup the feature-tour for the admin/settings page.
* This is intended as a contextual help (when pressing F1)

View File

@ -1032,7 +1032,7 @@ angular.module('application.router', ['ui.router'])
resolve: {
settingsPromise: ['Setting', function (Setting) {
return Setting.query({
names: `['twitter_name', 'about_title', 'about_body', 'tracking_id', 'facebook_app_id', \
names: `['twitter_name', 'about_title', 'about_body', 'tracking_id', 'facebook_app_id', 'email_from', \
'privacy_body', 'privacy_dpo', 'about_contacts', 'book_overlapping_slots', 'invoicing_module', \
'home_blogpost', 'machine_explications_alert', 'training_explications_alert', 'slot_duration', \
'training_information_message', 'subscription_explications_alert', 'event_explications_alert', \
@ -1040,8 +1040,8 @@ angular.module('application.router', ['ui.router'])
'booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', 'feature_tour_display', \
'booking_cancel_delay', 'main_color', 'secondary_color', 'spaces_module', 'twitter_analytics', \
'fablab_name', 'name_genre', 'reminder_enable', 'plans_module', \
'reminder_delay', 'visibility_yearly', 'visibility_others', 'email_from', \
'display_name_enable', 'machines_sort_by', 'fab_analytics', \
'reminder_delay', 'visibility_yearly', 'visibility_others', 'allowed_cad_extensions', \
'display_name_enable', 'machines_sort_by', 'fab_analytics', 'allowed_cad_mime_types' \
'link_name', 'home_content', 'home_css', 'phone_required']` }).$promise;
}],
privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }],

View File

@ -17,3 +17,45 @@
</div>
</div>
</div>
<div class="panel panel-default m-t-lg">
<div class="panel-heading">
<span class="font-sbold" translate>{{ 'app.admin.projects.settings.cad_files' }}</span>
</div>
<div class="panel-body">
<div class="row">
<h3 class="m-l" translate>{{ 'app.admin.projects.settings.validation' }}</h3>
<p class="alert alert-warning m-h-md" translate>{{ 'app.admin.projects.settings.validation_info' }}</p>
<div class="col-md-5">
<text-setting name="allowed_cad_extensions"
settings="allSettings"
label="app.admin.projects.settings.extensions"
fa-icon="fa-tag"
placeholder="pdf svg stl">
</text-setting>
</div>
<div class="col-md-5 col-md-offset-2">
<text-setting name="allowed_cad_mime_types"
settings="allSettings"
label="app.admin.projects.settings.mime_types"
fa-icon="fa-file-o"
placeholder="application/pdf image/xml+svg model/stl">
</text-setting>
</div>
<form name="mimeTestForm" class="col-md-6 m-t-lg" ng-upload="onTestFileComplete(content)" upload-options-enable-rails-csrf="true" action="/api/files/mime_type">
<label for="testFile" class="control-label" translate>{{ 'app.admin.projects.settings.test_file' }}</label>
<div class="fileinput input-group" data-provides="fileinput" ng-class="fileinputClass()">
<div class="form-control" data-trigger="fileinput">
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
</div>
<span class="input-group-addon btn btn-default btn-file">
<span class="fileinput-new" translate>{{ 'app.admin.projects.settings.set_a_file' }}</span>
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
<input type="file" id="testFile" name="attachment" accept="*/*" required>
</span>
</div>
<input type="submit" class="btn btn-warning" ng-disabled="mimeTestForm.$invalid || $isUploading">
</form>
</div>
</div>
</div>

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
# API Controller for handling special actions on files
class API::FilesController < API::ApiController
before_action :authenticate_user!
# test the mime type of the uploaded file
def mime
authorize :file
content_type = Marcel::MimeType.for Pathname.new(file_params.path)
render json: { type: content_type }
end
private
def file_params
params.require(:attachment)
end
end

View File

@ -90,7 +90,9 @@ class Setting < ApplicationRecord
recaptcha_secret_key
feature_tour_display
email_from
disqus_shortname] }
disqus_shortname
allowed_cad_extensions
allowed_cad_mime_types] }
def value
last_value = history_values.order(HistoryValue.arel_table['created_at'].desc).first
last_value&.value

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Check the access policies for API::FilesController
class FilePolicy < ApplicationPolicy
def mime?
user.admin?
end
end

View File

@ -33,11 +33,9 @@ class ProjectCaoUploader < CarrierWave::Uploader::Base
private
def check_content_type_whitelist!(new_file)
require 'mimemagic'
content_type = Marcel::MimeType.for Pathname.new(new_file.file)
content_type = MimeMagic.by_magic(File.open(new_file.file))
if content_type_whitelist && !whitelisted_content_type?(content_type)
if content_type_whitelist && content_type && !whitelisted_content_type?(content_type)
raise CarrierWave::IntegrityError,
I18n.translate(:'errors.messages.content_type_whitelist_error',
content_type: content_type,

View File

@ -144,6 +144,14 @@ en:
disqus: "Disqus"
disqus_info: "If you want to enable your members and visitors to comment on projects, you can enable the Disqus forums by setting the following parameter. Visit <a href='https://help.disqus.com/customer/portal/articles/466208-what-s-a-shortname-' target='_blank'>the Disqus website</a> for more information."
shortname: "Shortname"
cad_files: "CAD files"
validation: "Validation"
validation_info: "Users can upload CAD (Computer Aided Design) files with the documentation of their projects. You can specify which files types are allowed. Use the test input below to determine the MIME type of a file."
extensions: "Allowed extensions"
mime_types: "Allowed MIME types"
test_file: "Test a file"
set_a_file: "Select a file"
file_is_TYPE: "MIME type of this file is {TYPE}"
#track and monitor the trainings
trainings:
trainings_monitoring: "Trainings monitoring"

View File

@ -144,6 +144,14 @@ fr:
disqus: "Disqus"
disqus_info: "Si vous voulez permettre à vos membres et visiteurs de commenter les projets, vous pouvez activer les forums Disqus en définissant le paramètre suivant. Rendez-vous sur <a href='https://help.disqus.com/customer/portal/articles/466208-what-s-a-shortname-' target='_blank'>le site web de Disqus</a> pour plus d'informations."
shortname: "Nom court"
cad_files: "Fichier CAO"
validation: "Validation"
validation_info: "Les utilisateurs peuvent téléverser des fichiers de CAO (Conception Assistée par Ordinateur) avec la documentation de leurs projets. Vous pouvez spécifier quels types de fichiers sont autorisés. Utilisez le champ de test ci-dessous pour déterminer le type MIME d'un fichier."
extensions: "Extensions autorisées"
mime_types: "Types MIME autorisés"
test_file: "Tester un fichier"
set_a_file: "Sélectionner un fichier"
file_is_TYPE: "Le type MIME de ce fichier est {TYPE}"
#track and monitor the trainings
trainings:
trainings_monitoring: "Suivi formations"

View File

@ -167,6 +167,9 @@ Rails.application.routes.draw do
# FabAnalytics
get 'analytics/data' => 'analytics#data'
# test MIME type
post 'files/mime_type' => 'files#mime'
end
# rss

View File

@ -120,7 +120,9 @@ namespace :fablab do
%w[_ RECAPTCHA_SECRET_KEY recaptcha_secret_key],
%w[_ FEATURE_TOUR_DISPLAY feature_tour_display once],
%w[_ DEFAULT_MAIL_FROM email_from],
%w[_ DISQUS_SHORTNAME disqus_shortname]
%w[_ DISQUS_SHORTNAME disqus_shortname],
%w[_ ALLOWED_EXTENSIONS allowed_cad_extensions],
%w[_ ALLOWED_MIME_TYPES allowed_cad_mime_types]
]
mapping.each do |m|