vuefilemanager v1.4-beta.1

This commit is contained in:
carodej
2020-04-30 10:55:36 +02:00
parent 968b12c4ac
commit 606c1895a9
16 changed files with 275 additions and 32 deletions

View File

@@ -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']);

View File

@@ -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
*

View File

@@ -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

File diff suppressed because one or more lines are too long

View File

@@ -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'
}

View File

@@ -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;

View File

@@ -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])

View File

@@ -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:",

View File

@@ -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:",

View File

@@ -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
},

View File

@@ -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

View 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>

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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');
});