v0.1 Blacklist and Exif data

This commit is contained in:
Miloš Holba
2020-09-05 14:35:51 +02:00
committed by Peter Papp
parent fd6aa5c6b2
commit 0e12029efc
14 changed files with 274 additions and 3 deletions
+4
View File
@@ -67,6 +67,10 @@ class FileManagerFile extends Model
'file_url' 'file_url'
]; ];
protected $casts = [
'meta_data' => 'array',
];
/** /**
* Set routes with public access * Set routes with public access
* *
+6
View File
@@ -529,3 +529,9 @@ function get_pretty_name($basename, $name, $mimetype)
return $name . '.' . $mimetype; return $name . '.' . $mimetype;
} }
function get_image_meta_data($file)
{
if(get_file_type($file->getMimeType()) === 'image') {
return exif_read_data($file);
}
}
@@ -2,6 +2,7 @@
namespace App\Http\Requests\FileFunctions; namespace App\Http\Requests\FileFunctions;
use App\Rules\MimetypeBlacklistValidation;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@@ -26,7 +27,7 @@ class UploadRequest extends FormRequest
{ {
return [ return [
'parent_id' => 'required|integer', 'parent_id' => 'required|integer',
'file' => 'required|file', 'file' => ['required','file' , new MimetypeBlacklistValidation]
]; ];
} }
} }
+3
View File
@@ -257,6 +257,8 @@ class Editor
// If last then process file // If last then process file
if ($request->boolean('is_last')) { if ($request->boolean('is_last')) {
$meta_data = get_image_meta_data($file);
$disk_local = Storage::disk('local'); $disk_local = Storage::disk('local');
$unique_id = get_unique_id(); $unique_id = get_unique_id();
@@ -292,6 +294,7 @@ class Editor
'mimetype' => get_file_type_from_mimetype($file_mimetype), 'mimetype' => get_file_type_from_mimetype($file_mimetype),
'type' => get_file_type($file_mimetype), 'type' => get_file_type($file_mimetype),
'folder_id' => $request->parent_id, 'folder_id' => $request->parent_id,
'meta_data' => $meta_data,
'name' => $user_file_name, 'name' => $user_file_name,
'unique_id' => $unique_id, 'unique_id' => $unique_id,
'basename' => $disk_file_name, 'basename' => $disk_file_name,
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class MimetypeBlacklistValidation implements Rule
{
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$mimetype_blacklist = explode(',' ,get_setting('mimetypes_blacklist'));
$fileMimetype = explode('/' ,$value->getMimeType());
return !array_intersect($fileMimetype , $mimetype_blacklist);
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
abort (415,'Type of this mime type is not allowed.');
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddExifDataToFileManagerFilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('file_manager_files', function (Blueprint $table) {
$table->longText('meta_data')->after('type')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('file_manager_files', function (Blueprint $table) {
//
});
}
}
@@ -56,12 +56,21 @@
<CopyInput class="copy-sharelink" size="small" :value="fileInfoDetail.shared.link"/> <CopyInput class="copy-sharelink" size="small" :value="fileInfoDetail.shared.link"/>
</div> </div>
</ListInfoItem> </ListInfoItem>
<div @click="this.showMetaData">
<ListInfoItem v-if="fileInfoDetail.meta_data"
:title="$t('file_detail_meta.meta_data')"
class="meta-data">
<ImageMetaData v-if="this.metaDataShow" />
</ListInfoItem>
</div>
</ListInfo> </ListInfo>
</div> </div>
</template> </template>
<script> <script>
import {Edit2Icon, LockIcon, UnlockIcon, ImageIcon, VideoIcon, FolderIcon, FileIcon} from 'vue-feather-icons' import {Edit2Icon, LockIcon, UnlockIcon, ImageIcon, VideoIcon, FolderIcon, FileIcon} from 'vue-feather-icons'
import ImageMetaData from '@/components/FilesView/ImageMetaData'
import FilePreview from '@/components/FilesView/FilePreview' import FilePreview from '@/components/FilesView/FilePreview'
import CopyInput from '@/components/Others/Forms/CopyInput' import CopyInput from '@/components/Others/Forms/CopyInput'
import ListInfoItem from '@/components/Others/ListInfoItem' import ListInfoItem from '@/components/Others/ListInfoItem'
@@ -72,6 +81,7 @@
export default { export default {
name: 'FileInfoPanel', name: 'FileInfoPanel',
components: { components: {
ImageMetaData,
ListInfoItem, ListInfoItem,
ListInfo, ListInfo,
FilePreview, FilePreview,
@@ -131,7 +141,15 @@
return this.fileInfoDetail.shared.protected return this.fileInfoDetail.shared.protected
} }
}, },
data() {
return {
metaDataShow: false
}
},
methods: { methods: {
showMetaData() {
this.metaDataShow = !this.metaDataShow
},
shareItemOptions() { shareItemOptions() {
// Open share item popup // Open share item popup
events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail}) events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail})
@@ -212,6 +230,9 @@
width: 100%; width: 100%;
} }
} }
.meta-data{
cursor: pointer;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
@@ -0,0 +1,75 @@
<template>
<div>
<ul class="meta-data-list">
<li v-if="fileInfoDetail.meta_data.Artist"> {{$t('file_detail_meta.author')}}
<p> {{fileInfoDetail.meta_data.Artist}} </p> </li>
<li v-if="fileInfoDetail.meta_data.DateTimeOriginal">{{$t('file_detail_meta.time_data')}}
<p> {{fileInfoDetail.meta_data.DateTimeOriginal}} </p> </li>
<li v-if="fileInfoDetail.meta_data.Make">{{$t('file_detail_meta.make')}}
<p> {{fileInfoDetail.meta_data.Make}} </p> </li>
<li v-if="fileInfoDetail.meta_data.Model">{{$t('file_detail_meta.model')}}
<p> {{fileInfoDetail.meta_data.Model}} </p> </li>
<li v-if="fileInfoDetail.meta_data.COMPUTED.CCDWidth">{{$t('file_detail_meta.camera_lens')}}
<p> {{fileInfoDetail.meta_data.COMPUTED.CCDWidth}} </p> </li>
<li v-if="fileInfoDetail.meta_data.COMPUTED.ApertureFNumber">{{$t('file_detail_meta.aperature')}}
<p> {{fileInfoDetail.meta_data.COMPUTED.ApertureFNumber}} </p> </li>
<li v-if="fileInfoDetail.meta_data.ISOSpeedRatings">{{$t('file_detail_meta.iso')}}
<p> {{fileInfoDetail.meta_data.ISOSpeedRatings}} </p> </li>
<li v-if="fileInfoDetail.meta_data.FocalLength">{{$t('file_detail_meta.focal')}}
<p> {{fileInfoDetail.meta_data.FocalLength}} </p> </li>
<li v-if="fileInfoDetail.meta_data.ExposureTime">{{$t('file_detail_meta.exposure')}}
<p> {{fileInfoDetail.meta_data.ExposureTime}} </p> </li>
<li v-else>{{$t('file_detail_meta.not_avaible')}} </li>
</ul>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: 'ImageMetaData',
computed: {
...mapGetters(['fileInfoDetail']),
},
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
.meta-data-list {
list-style: none;
padding: 0px;
margin: 0px;
li {
margin-top:10px;
@include font-size(14);
font-weight: bold;
color: $text;
p {
@include font-size(13);
color: $text;
}
}
}
@media (prefers-color-scheme: dark) {
li {
color:$dark_mode_text_primary !important;
p {
color: $dark_mode_text_primary !important;
}
}
}
</style>
+4
View File
@@ -145,6 +145,10 @@ const Helpers = {
if (error.response.status === 500) if (error.response.status === 500)
isNotGeneralError = false isNotGeneralError = false
//Break if mimetype of file is in blacklist
if(error.response.status === 415)
isNotGeneralError = false
// Show Error // Show Error
if (attempts === 3) if (attempts === 3)
this.$isSomethingWrong() this.$isSomethingWrong()
+20
View File
@@ -208,6 +208,9 @@
"username_plac": "输入您的邮件用户名" "username_plac": "输入您的邮件用户名"
}, },
"others": { "others": {
"mimetypes_blacklist": "Mimetypes Blacklist",
"mimetypes_blacklist_plac":"Add mimetypes to Blacklist" ,
"mimetypes_blacklist_help" :"If you want ban some type of files to upload just add them to blacklist like this: php,mp3,jpeg <br/> Use a comma between each mime type. Don't use a dot before mimetypes." ,
"section_cache": "Application Cache", "section_cache": "Application Cache",
"cache_disclaimer": "Did you change anything in your .env file or change your stripe credentials? Then clear your cache.", "cache_disclaimer": "Did you change anything in your .env file or change your stripe credentials? Then clear your cache.",
"cache_clear": "Clear Cache", "cache_clear": "Clear Cache",
@@ -295,6 +298,19 @@
"size": "大小", "size": "大小",
"where": "地址" "where": "地址"
}, },
"file_detail_meta": {
"meta_data": "Metadata",
"author": "Author",
"time_data": "Original time data",
"make": "Camera",
"model": "Model",
"camera_lens": "Camera lens",
"aperature": "Aperture F Number",
"iso": "ISO",
"focal": "Focal length",
"exposure": "Exposure time",
"not_avaible": "Metadata not avaible"
},
"folder": { "folder": {
"empty": "空的", "empty": "空的",
"item_counts": "{count} 个文件 | {count} 个文件" "item_counts": "{count} 个文件 | {count} 个文件"
@@ -473,6 +489,10 @@
}, },
"title": "选择付款方式" "title": "选择付款方式"
}, },
"popup_mimetypes_blacklist": {
"title": "Sorry",
"message": "File of this type is not allowed to upload."
},
"popup_create_folder": { "popup_create_folder": {
"folder_default_name": "新文件夹", "folder_default_name": "新文件夹",
"title": "请填入新文件夹名称" "title": "请填入新文件夹名称"
+20
View File
@@ -210,6 +210,9 @@
"username_plac": "Type your mail username" "username_plac": "Type your mail username"
}, },
"others": { "others": {
"mimetypes_blacklist": "Mimetypes Blacklist",
"mimetypes_blacklist_plac":"Add mimetypes to Blacklist" ,
"mimetypes_blacklist_help" :"If you want ban some type of files to upload just add them to blacklist like this: php,mp3,jpeg <br/> Use a comma between each mime type. Don't use a dot before mimetypes." ,
"section_cache": "Application Cache", "section_cache": "Application Cache",
"cache_disclaimer": "Did you change anything in your .env file or change your Stripe credentials? Then clear your cache.", "cache_disclaimer": "Did you change anything in your .env file or change your Stripe credentials? Then clear your cache.",
"cache_clear": "Clear Cache", "cache_clear": "Clear Cache",
@@ -297,6 +300,19 @@
"size": "Size", "size": "Size",
"where": "Where" "where": "Where"
}, },
"file_detail_meta": {
"meta_data": "Metadata",
"author": "Author",
"time_data": "Original time data",
"make": "Camera",
"model": "Model",
"camera_lens": "Camera lens",
"aperature": "Aperture F Number",
"iso": "ISO",
"focal": "Focal length",
"exposure": "Exposure time",
"not_avaible": "Metadata not avaible"
},
"folder": { "folder": {
"empty": "Empty", "empty": "Empty",
"item_counts": "{count} Item | {count} Items" "item_counts": "{count} Item | {count} Items"
@@ -475,6 +491,10 @@
}, },
"title": "Choose Payment Method" "title": "Choose Payment Method"
}, },
"popup_mimetypes_blacklist": {
"title": "Sorry",
"message": "File of this type is not allowed to upload."
},
"popup_create_folder": { "popup_create_folder": {
"folder_default_name": "New Folder", "folder_default_name": "New Folder",
"title": "Please enter your new folder name" "title": "Please enter your new folder name"
+20
View File
@@ -210,6 +210,9 @@
"username_plac": "Zadajte svoje používateľské meno pre poštu" "username_plac": "Zadajte svoje používateľské meno pre poštu"
}, },
"others": { "others": {
"mimetypes_blacklist": "Čierna listina mimetypov",
"mimetypes_blacklist_plac":"Pridajte mimetypy do Čiernej listiny",
"mimetypes_blacklist_help" :"Ak chcete zakázať nahrávanie niektorých typov súborov, jednoducho ich pridajte na čiernu listinu, príklad: php, mp3, jpeg <br/> Medzi mimetypmi použite čiarku. Nevkladajte bodku pred mimetyp." ,
"section_cache": "Aplikačná pamäť", "section_cache": "Aplikačná pamäť",
"cache_disclaimer": "Zmenili ste niečo v .env súbore alebo ste zmenili Stripe poverenia? Vymažte aplikačnú pamäť.", "cache_disclaimer": "Zmenili ste niečo v .env súbore alebo ste zmenili Stripe poverenia? Vymažte aplikačnú pamäť.",
"cache_clear": "Vymazať aplikačnú pamäť", "cache_clear": "Vymazať aplikačnú pamäť",
@@ -297,6 +300,19 @@
"size": "Veľkosť", "size": "Veľkosť",
"where": "Umiestnenie" "where": "Umiestnenie"
}, },
"file_detail_meta": {
"meta_data": "Metadata",
"author": "Autor",
"time_data": "Pôvodných časový údaj",
"make": "Fotoaparát",
"model": "Model",
"camera_lens": "Objektív fotoaparátu",
"aperature": "Clona",
"iso": "ISO",
"focal": "Ohnisková vzdialenosť",
"exposure": "Doba expozície",
"not_avaible": "Metadáta nie sú k dispozícii"
},
"folder": { "folder": {
"empty": "Prázdne", "empty": "Prázdne",
"item_counts": "{count} Položka | {count} Položky" "item_counts": "{count} Položka | {count} Položky"
@@ -475,6 +491,10 @@
}, },
"title": "Vyberte si metódu platby" "title": "Vyberte si metódu platby"
}, },
"popup_mimetypes_blacklist": {
"title": "Ospravelnujume sa",
"message": "Nieje povolené nahrávať tento typ súboru."
},
"popup_create_folder": { "popup_create_folder": {
"folder_default_name": "Nový priečinok", "folder_default_name": "Nový priečinok",
"title": "Prosím, vložte názov nového priečinka" "title": "Prosím, vložte názov nového priečinka"
+7
View File
@@ -122,6 +122,13 @@ const actions = {
message: i18n.t('popup_exceed_limit.message') message: i18n.t('popup_exceed_limit.message')
}) })
break; break;
case 415:
events.$emit('alert:open', {
emoji: '😬',
title: i18n.t('popup_mimetypes_blacklist.title'),
message: i18n.t('popup_mimetypes_blacklist.message')
})
break;
case 413: case 413:
events.$emit('alert:open', { events.$emit('alert:open', {
emoji: '😟', emoji: '😟',
@@ -80,6 +80,21 @@
</ValidationProvider> </ValidationProvider>
</div> </div>
<div class="block-wrapper">
<label>{{ $t('admin_settings.others.mimetypes_blacklist') }}:</label>
<small class="input-help" v-html="$t('admin_settings.others.mimetypes_blacklist_help')"></small>
</div>
<div class="block-wrapper">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Mimetypes Blacklist"
v-slot="{ errors }">
<textarea rows="2" @input="$updateText('/settings', 'mimetypes_blacklist', app.mimetypesBlacklist)" v-model="app.mimetypesBlacklist"
:placeholder="$t('admin_settings.others.mimetypes_blacklist_plac')"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<FormLabel class="mt-70"> <FormLabel class="mt-70">
{{ $t('admin_settings.others.section_cache') }} {{ $t('admin_settings.others.section_cache') }}
</FormLabel> </FormLabel>
@@ -154,7 +169,7 @@
mounted() { mounted() {
axios.get('/api/settings', { axios.get('/api/settings', {
params: { params: {
column: 'contact_email|google_analytics|storage_default|registration|storage_limitation' column: 'contact_email|google_analytics|storage_default|registration|storage_limitation|mimetypes_blacklist'
} }
}) })
.then(response => { .then(response => {
@@ -166,6 +181,7 @@
defaultStorage: response.data.storage_default, defaultStorage: response.data.storage_default,
userRegistration: parseInt(response.data.registration), userRegistration: parseInt(response.data.registration),
storageLimitation: parseInt(response.data.storage_limitation), storageLimitation: parseInt(response.data.storage_limitation),
mimetypesBlacklist : response.data.mimetypes_blacklist
} }
}) })
} }