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:
parent
743f3e510a
commit
5c152412db
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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; }],
|
||||
|
@ -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>
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Check the access policies for API::FilesController
|
||||
class FilePolicy < ApplicationPolicy
|
||||
def mime?
|
||||
user.admin?
|
||||
end
|
||||
end
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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|
|
||||
|
Loading…
x
Reference in New Issue
Block a user