mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
vuefilemanager v1.4-beta.1
This commit is contained in:
@@ -34,7 +34,7 @@ class FavouriteController extends Controller
|
||||
if ($folder->user_id !== $user->id) abort(403);
|
||||
|
||||
// Add folder to user favourites
|
||||
$user->favourites()->attach($request->unique_id);
|
||||
$user->favourites()->syncWithoutDetaching($request->unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
|
||||
@@ -29,8 +29,12 @@ class FileSharingController extends Controller
|
||||
public function index($token)
|
||||
{
|
||||
// Get shared token
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)
|
||||
->firstOrFail();
|
||||
$shared = Share::where(\DB::raw('BINARY `token`'), $token)
|
||||
->first();
|
||||
|
||||
if (!$shared) {
|
||||
return view("index");
|
||||
}
|
||||
|
||||
// Delete old access_token if exist
|
||||
Cookie::queue('shared_access_token', '', -1);
|
||||
@@ -186,7 +190,7 @@ class FileSharingController extends Controller
|
||||
public function get_private_navigation_tree(Request $request)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($shared->item_id, $shared);
|
||||
@@ -203,7 +207,7 @@ class FileSharingController extends Controller
|
||||
'unique_id' => $shared->item_id,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'public',
|
||||
'folders' => $folders,
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -233,11 +237,109 @@ class FileSharingController extends Controller
|
||||
'unique_id' => $shared->item_id,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'public',
|
||||
'folders' => $folders,
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search private files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $token
|
||||
* @return Collection
|
||||
*/
|
||||
public function search_private(Request $request)
|
||||
{
|
||||
// Get shared
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
|
||||
// Get all children content
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get accessible folders
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Filter files to only accessible files
|
||||
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids) {
|
||||
return in_array($file->folder_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Filter folders to only accessible folders
|
||||
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
|
||||
return in_array($folder->unique_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search public files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $token
|
||||
* @return Collection
|
||||
*/
|
||||
public function search_public(Request $request, $token)
|
||||
{
|
||||
// Get shared
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if folder is protected
|
||||
if ($shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
|
||||
// Get all children content
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get accessible folders
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Filter files
|
||||
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids, $token) {
|
||||
|
||||
// Set public urls
|
||||
$file->setPublicUrl($token);
|
||||
|
||||
// check if item is in accessible folders
|
||||
return in_array($file->folder_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Filter folders
|
||||
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
|
||||
|
||||
// check if item is in accessible folders
|
||||
return in_array($folder->unique_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folders and files
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Tools;
|
||||
|
||||
use App;
|
||||
use App\Share;
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
@@ -91,7 +92,16 @@ class Editor
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// TODO: delete folder shared record
|
||||
// Get folder shared record
|
||||
$shared = Share::where('user_id', $user->id)
|
||||
->where('type', '=', 'folder')
|
||||
->where('item_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Delete folder shared record
|
||||
if ($shared) {
|
||||
$shared->delete();
|
||||
}
|
||||
|
||||
// Force delete children files
|
||||
if ($request->force_delete) {
|
||||
@@ -142,7 +152,16 @@ class Editor
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// TODO: delete file shared record
|
||||
// Get folder shared record
|
||||
$shared = Share::where('user_id', $user->id)
|
||||
->where('type', '=', 'file')
|
||||
->where('item_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Delete file shared record
|
||||
if ($shared) {
|
||||
$shared->delete();
|
||||
}
|
||||
|
||||
// Force delete file
|
||||
if ($request->force_delete) {
|
||||
|
||||
2
public/js/main.js
vendored
2
public/js/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -59,7 +59,7 @@
|
||||
'appSize', 'isLogged', 'isGuest'
|
||||
]),
|
||||
layout() {
|
||||
if (includes(['VerifyByPassword', 'SharedContent', 'SignIn', 'SignUp', 'ForgottenPassword', 'CreateNewPassword'], this.$route.name)) {
|
||||
if (includes(['VerifyByPassword', 'SharedPage', 'NotFoundShared', 'SignIn', 'SignUp', 'ForgottenPassword', 'CreateNewPassword'], this.$route.name)) {
|
||||
return 'unauthorized'
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span @click.stop="showItemActions" class="show-actions" v-if="$isMobile() && ! ( $checkPermission('visitor') && isFolder )">
|
||||
<span @click.stop="showItemActions" class="show-actions"
|
||||
v-if="$isMobile() && ! ( $checkPermission('visitor') && isFolder ) && canShowMobileOptions">
|
||||
<FontAwesomeIcon icon="ellipsis-h" class="icon-action"></FontAwesomeIcon>
|
||||
</span>
|
||||
</div>
|
||||
@@ -87,7 +88,7 @@
|
||||
props: ['data'],
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'FilePreviewType', 'sharedDetail'
|
||||
'FilePreviewType', 'sharedDetail', 'contextMenu'
|
||||
]),
|
||||
isFolder() {
|
||||
return this.data.type === 'folder'
|
||||
@@ -102,7 +103,10 @@
|
||||
return !this.$isMobile()
|
||||
&& !this.$isThisLocation(['trash', 'trash-root'])
|
||||
&& !this.$checkPermission('visitor')
|
||||
&& (this.sharedDetail && this.sharedDetail.type !== 'file')
|
||||
&& !(this.sharedDetail && this.sharedDetail.type === 'file')
|
||||
},
|
||||
canShowMobileOptions() {
|
||||
return ! (this.sharedDetail && this.sharedDetail.type === 'file')
|
||||
},
|
||||
canDrag() {
|
||||
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
|
||||
@@ -194,7 +198,7 @@
|
||||
renameItem: debounce(function (e) {
|
||||
|
||||
// Prevent submit empty string
|
||||
if (e.target.innerText === '') return
|
||||
if (e.target.innerText.trim() === '') return
|
||||
|
||||
this.$store.dispatch('renameItem', {
|
||||
unique_id: this.data.unique_id,
|
||||
@@ -286,6 +290,7 @@
|
||||
max-height: 40px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
|
||||
&[contenteditable] {
|
||||
-webkit-user-select: text;
|
||||
|
||||
@@ -99,10 +99,13 @@
|
||||
return this.data.type === 'image'
|
||||
},
|
||||
canEditName() {
|
||||
return ! this.$isMobile() && ! this.$isThisLocation(['trash', 'trash-root']) && ! this.$checkPermission('visitor')
|
||||
return !this.$isMobile()
|
||||
&& !this.$isThisLocation(['trash', 'trash-root'])
|
||||
&& !this.$checkPermission('visitor')
|
||||
&& !(this.sharedDetail && this.sharedDetail.type === 'file')
|
||||
},
|
||||
canDrag() {
|
||||
return ! this.isDeleted && this.$checkPermission(['master', 'editor'])
|
||||
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
|
||||
},
|
||||
timeStamp() {
|
||||
return this.data.deleted_at ? this.$t('item_thumbnail.deleted_at', {time: this.data.deleted_at}) : this.data.created_at
|
||||
@@ -160,7 +163,7 @@
|
||||
if (this.$isMobile() && this.isFolder) {
|
||||
|
||||
// Go to folder
|
||||
if ( this.$isThisLocation('public') ) {
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [this.data, false])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.data, false])
|
||||
@@ -190,7 +193,7 @@
|
||||
|
||||
if (this.isFolder) {
|
||||
|
||||
if ( this.$isThisLocation('public') ) {
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [this.data, false])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.data, false])
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
"download_file": "Download File",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"page_shared_404": {
|
||||
"subtitle": "The content you are finding was probably deleted.",
|
||||
"title": "Not Found :("
|
||||
},
|
||||
"page_create_password": {
|
||||
"title": "Only One Step to Log In",
|
||||
"subtitle": "Create your new password here:",
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
"download_file": "Stiahnúť súbor",
|
||||
"submit": "Potvrdiť"
|
||||
},
|
||||
"page_shared_404": {
|
||||
"subtitle": "Obsah ktorý hľadáš bol pravdepodobne vymazaný.",
|
||||
"title": "Obsah sa nenašiel :("
|
||||
},
|
||||
"page_create_password": {
|
||||
"title": "Iba jeden krok pre prihlásenie",
|
||||
"subtitle": "Vytvorte si nové heslo tu:",
|
||||
|
||||
15
resources/js/router.js
vendored
15
resources/js/router.js
vendored
@@ -3,7 +3,8 @@ import Router from 'vue-router'
|
||||
|
||||
import Index from './views/Auth/SignIn'
|
||||
import SignUp from './views/Auth/SignUp'
|
||||
import SharedContent from './views/Shared/SharedContent'
|
||||
import SharedPage from './views/Shared/SharedPage'
|
||||
import NotFoundShared from './views/Shared/NotFoundShared'
|
||||
import ForgottenPassword from './views/Auth/ForgottenPassword'
|
||||
import CreateNewPassword from './views/Auth/CreateNewPassword'
|
||||
|
||||
@@ -48,9 +49,17 @@ const router = new Router({
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SharedContent',
|
||||
name: 'SharedPage',
|
||||
path: '/shared/:token',
|
||||
component: SharedContent,
|
||||
component: SharedPage,
|
||||
meta: {
|
||||
requiresAuth: false
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'NotFoundShared',
|
||||
path: '/shared-not-found',
|
||||
component: NotFoundShared,
|
||||
meta: {
|
||||
requiresAuth: false
|
||||
},
|
||||
|
||||
26
resources/js/store/modules/fileBrowser.js
vendored
26
resources/js/store/modules/fileBrowser.js
vendored
@@ -23,7 +23,7 @@ const actions = {
|
||||
events.$emit('show:content')
|
||||
|
||||
// Go to files view
|
||||
if (!includes(['Files', 'SharedContent'], router.currentRoute.name)) {
|
||||
if (!includes(['Files', 'SharedPage'], router.currentRoute.name)) {
|
||||
router.push({name: 'Files'})
|
||||
}
|
||||
|
||||
@@ -155,18 +155,28 @@ const actions = {
|
||||
})
|
||||
})
|
||||
},
|
||||
getSearchResult: (context, query) => {
|
||||
context.commit('FLUSH_DATA')
|
||||
context.commit('LOADING_STATE', true)
|
||||
context.commit('CHANGE_SEARCHING_STATE', true)
|
||||
getSearchResult: ({commit, getters}, query) => {
|
||||
commit('FLUSH_DATA')
|
||||
commit('LOADING_STATE', true)
|
||||
commit('CHANGE_SEARCHING_STATE', true)
|
||||
|
||||
// Get route
|
||||
let route = undefined
|
||||
|
||||
if (getters.sharedDetail && getters.sharedDetail.protected)
|
||||
route = '/api/search/private'
|
||||
else if (getters.sharedDetail && !getters.sharedDetail.protected)
|
||||
route = '/api/search/public/' + router.currentRoute.params.token
|
||||
else
|
||||
route = '/api/search'
|
||||
|
||||
axios
|
||||
.get(context.getters.api + '/search', {
|
||||
.get(route, {
|
||||
params: {query: query}
|
||||
})
|
||||
.then(response => {
|
||||
context.commit('LOADING_STATE', false)
|
||||
context.commit('GET_DATA', response.data)
|
||||
commit('LOADING_STATE', false)
|
||||
commit('GET_DATA', response.data)
|
||||
})
|
||||
.catch(() => {
|
||||
// Show error message
|
||||
|
||||
53
resources/js/views/Shared/NotFoundShared.vue
Normal file
53
resources/js/views/Shared/NotFoundShared.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<AuthContentWrapper ref="auth">
|
||||
|
||||
<!--Password reset link sended-->
|
||||
<AuthContent name="not-found" :visible="true">
|
||||
<img class="logo" :src="config.app_logo" :alt="config.app_name">
|
||||
<h1>{{ $t('page_shared_404.title') }}</h1>
|
||||
<h2>{{ $t('page_shared_404.subtitle') }}</h2>
|
||||
|
||||
<span class="additional-link">{{ $t('page_registration.have_an_account') }}
|
||||
<router-link :to="{name: 'SignIn'}">
|
||||
{{ $t('page_forgotten_password.password_remember_button') }}
|
||||
</router-link>
|
||||
</span>
|
||||
</AuthContent>
|
||||
</AuthContentWrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AuthContentWrapper from '@/components/Auth/AuthContentWrapper'
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import AuthContent from '@/components/Auth/AuthContent'
|
||||
import AuthButton from '@/components/Auth/AuthButton'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import {mapGetters} from 'vuex'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'NotFoundShared',
|
||||
components: {
|
||||
AuthContentWrapper,
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
AuthContent,
|
||||
AuthButton,
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
@import '@assets/vue-file-manager/_auth';
|
||||
</style>
|
||||
@@ -41,7 +41,7 @@
|
||||
<div v-if="currentPage === 'page-files'" id="files-view" :class="filesViewWidth">
|
||||
<div id="single-file" v-if="sharedDetail.type === 'file'">
|
||||
<div class="single-file-wrapper">
|
||||
<FileItemGrid v-if="sharedFile" :data="sharedFile"/>
|
||||
<FileItemGrid v-if="sharedFile" :data="sharedFile" :context-menu="false"/>
|
||||
|
||||
<ButtonBase @click.native="download" class="download-button" button-style="theme">
|
||||
{{ $t('page_shared.download_file') }}
|
||||
@@ -84,7 +84,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'SharedContent',
|
||||
name: 'SharedPage',
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
@@ -224,6 +224,15 @@
|
||||
this.getFiles()
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
console.log('error not found');
|
||||
|
||||
if (error.response.status == 404) {
|
||||
|
||||
this.$router.push({name: 'NotFoundShared'})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -253,6 +262,7 @@
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: grid;
|
||||
height: 100%;
|
||||
|
||||
.single-file-wrapper {
|
||||
margin: auto;
|
||||
21
resources/sass/vue-file-manager/_auth.scss
vendored
21
resources/sass/vue-file-manager/_auth.scss
vendored
@@ -79,6 +79,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 490px) {
|
||||
|
||||
.auth-form {
|
||||
h1 {
|
||||
@include font-size(22);
|
||||
}
|
||||
|
||||
h2 {
|
||||
@include font-size(18);
|
||||
}
|
||||
|
||||
input {
|
||||
min-width: initial;
|
||||
}
|
||||
|
||||
.additional-link {
|
||||
@include font-size(15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.auth-form {
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ $light_mode_vignette: rgba(9, 8, 12, 0.15);
|
||||
// Dark Mode
|
||||
$dark_mode_vignette: rgba(0, 0, 0, 0.3);
|
||||
$dark_mode_background: #1a1f25;
|
||||
$dark_mode_foreground: #1c222d;
|
||||
$dark_mode_foreground: #202733;
|
||||
$dark_mode_text_primary: #B8C4D0;
|
||||
$dark_mode_text_secondary: #667b90;
|
||||
$dark_mode_vignette: rgba(22, 23, 27, 0.70);
|
||||
|
||||
@@ -30,9 +30,11 @@ Route::group(['middleware' => ['api']], function () {
|
||||
Route::get('/folders/{unique_id}/public/{token}', 'Sharing\FileSharingController@get_public_folders');
|
||||
Route::get('/navigation/public/{token}', 'Sharing\FileSharingController@get_public_navigation_tree');
|
||||
Route::post('/shared/authenticate/{token}', 'Sharing\FileSharingController@authenticate');
|
||||
Route::get('/search/public/{token}', 'Sharing\FileSharingController@search_public');
|
||||
Route::get('/files/{token}/public', 'Sharing\FileSharingController@file_public');
|
||||
Route::get('/shared/{token}', 'FileFunctions\ShareController@show');
|
||||
|
||||
|
||||
// User reset password
|
||||
Route::post('/password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
|
||||
Route::post('/password/reset', 'Auth\ResetPasswordController@reset');
|
||||
@@ -82,6 +84,7 @@ Route::group(['middleware' => ['auth:api', 'auth.shared', 'scope:visitor,editor'
|
||||
// Browse folders & files
|
||||
Route::get('/folders/{unique_id}/private', 'Sharing\FileSharingController@get_private_folders');
|
||||
Route::get('/navigation/private', 'Sharing\FileSharingController@get_private_navigation_tree');
|
||||
Route::get('/search/private', 'Sharing\FileSharingController@search_private');
|
||||
Route::get('/files/private', 'Sharing\FileSharingController@file_private');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user