Merge remote-tracking branch 'origin/version-v1.8.1'

# Conflicts:
#	config/vuefilemanager.php
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/contact-us.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared-page.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/landing-page.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-delete.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/profile.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/shared-files.js
#	public/chunks/shared-page.js
#	public/chunks/sign-up.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-password.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/views/FilePages/Files.vue
This commit is contained in:
Peter Papp
2021-02-07 18:05:56 +01:00
140 changed files with 17575 additions and 1524 deletions
@@ -26,6 +26,7 @@ class AppFunctionsController extends Controller
* @var array
*/
private $whitelist = [
'section_features',
'footer_content',
'get_started_description',
'get_started_title',
@@ -44,7 +45,7 @@ class AppFunctionsController extends Controller
'section_get_started',
'section_pricing_content',
'section_feature_boxes',
'section_features',
'allow_homepage',
];
/**
@@ -96,7 +96,7 @@ class BrowseController extends Controller
// Get User
$user = User::with(['latest_uploads' => function($query) {
$query->sortable();
$query->sortable(['created_at' => 'desc']);
}])
->where('id', Auth::id())
->first();
@@ -15,6 +15,7 @@ use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Http\Tools\Guardian;
use App\Http\Tools\Editor;
use App\FileManagerFolder;
use App\FileManagerFile;
use Exception;
@@ -114,6 +115,12 @@ class EditItemsController extends Controller
}
}
// If request have a change folder icon values set the folder icon
if ($request->type === 'folder' && $request->filled('folder_icon')) {
Editor::set_folder_icon($request->folder_icon, $unique_id);
}
// Rename Item
return Editor::rename_item($request, $unique_id);
}
@@ -150,6 +157,12 @@ class EditItemsController extends Controller
Guardian::check_item_access($item->folder_id, $shared);
}
// If request have a change folder icon values set the folder icon
if ($request->type === 'folder' && $request->filled('folder_icon')) {
Editor::set_folder_icon($request->folder_icon, $unique_id, $shared);
}
// Rename item
$item = Editor::rename_item($request, $unique_id, $shared);
@@ -315,6 +328,85 @@ class EditItemsController extends Controller
return $new_file;
}
/**
* User download folder via zip
*
* @param $unique_id
* @return string
*/
public function user_zip_folder(Request $request,$unique_id)
{
// Get user id
$user_id = Auth::id();
// Check permission to download for authenticated editor
if ($request->user()->tokenCan('editor')) {
// check if shared_token cookie exist
if (!$request->hasCookie('shared_token')) abort('401');
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Check access to requested directory
Guardian::check_item_access($unique_id, $shared);
}
// Get folder
$folder = FileManagerFolder::whereUserId($user_id)
->where('unique_id', $unique_id);
if (! $folder->exists()) {
abort(404, 'Requested folder doesn\'t exists.');
}
$zip = Editor::zip_folder($unique_id);
// Get file
return response([
'url' => route('zip', $zip->id),
'name' => $zip->basename,
], 200);
}
/**
* Guest download folder via zip
*
* @param Request $request
* @param $unique_id
* @param $token
* @return string
*/
public function guest_zip_folder($unique_id, $token)
{
// Get shared record
$shared = get_shared($token);
// Check access to requested folder
Guardian::check_item_access($unique_id, $shared);
// Get folder
$folder = FileManagerFolder::whereUserId($shared->user_id)
->where('unique_id', $unique_id);
if (! $folder->exists()) {
abort(404, 'Requested folder doesn\'t exists.');
}
$zip = Editor::zip_folder($unique_id, $shared);
// Get file
return response([
'url' => route('zip_public', [
'id' => $zip->id,
'token' => $shared->token,
]),
'name' => $zip->basename,
], 200);
}
/**
* User download multiple files via zip
*
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\FileFunctions;
use App\Http\Requests\Share\CreateShareRequest;
use App\Http\Requests\Share\UpdateShareRequest;
use App\Http\Resources\ShareResource;
use App\Notifications\SharedSendViaEmail;
use App\Zip;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Controllers\Controller;
@@ -12,8 +13,10 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
use App\Share;
use Validator;
class ShareController extends Controller
{
@@ -58,7 +61,17 @@ class ShareController extends Controller
];
// Return created shared record
return new ShareResource(Share::create($options));
$share = new ShareResource(Share::create($options));
// Send shared link via email
if ($request->has('emails')) {
foreach ($request->emails as $email) {
Notification::route('mail', $email)->notify(new SharedSendViaEmail($token));
}
}
return $share;
}
/**
@@ -96,7 +109,7 @@ class ShareController extends Controller
*/
public function destroy(Request $request)
{
foreach($request->input('tokens') as $token) {
foreach ($request->input('tokens') as $token) {
// Get sharing record
Share::where('token', $token)
@@ -117,4 +130,40 @@ class ShareController extends Controller
// Done
return response('Done!', 204);
}
/**
* Send shared link via email to recipients
*
* @param $token
* @param $request
*/
public function shared_send_via_email(Request $request, $token)
{
// Make validation of array of emails
$validator = Validator::make($request->all(), [
'emails.*' => 'required|email',
]);
// Return error
if ($validator->fails()) abort(400, 'Bad emails input');
// Get shared by token
$share = Share::where('token', $token)
->where('user_id', Auth::id())
->first();
// Demo preview
if (env('APP_DEMO')) {
return response('Done!', 204);
}
// Send shared link via email
if($request->has('emails')) {
foreach ($request->emails as $email) {
Notification::route('mail', $email)->notify(new SharedSendViaEmail($token));
}
}
return response('Done!', 204);
}
}
@@ -59,12 +59,12 @@ class TrashController extends Controller
* @param $unique_id
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function restore(Request $request, $unique_id)
public function restore(Request $request)
{
// Validate request
$validator = Validator::make($request->all(), [
'type' => 'required|string',
'to_home' => 'boolean',
$validator = Validator::make($request->input('data'), [
'*.type' => 'required|string',
'*.unique_id' => 'integer',
]);
// Return error
@@ -77,38 +77,41 @@ class TrashController extends Controller
return Demo::response_204();
}
// Get folder
if ($request->type === 'folder') {
foreach($request->input('data') as $restore_item) {
// Get folder
$item = FileManagerFolder::onlyTrashed()
->where('user_id', $user_id)
->where('unique_id', $unique_id)
->first();
if ($restore_item['type'] === 'folder') {
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->parent_id = 0;
$item->save();
// Get folder
$item = FileManagerFolder::onlyTrashed()
->where('user_id', $user_id)
->where('unique_id', $restore_item['unique_id'])
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->parent_id = 0;
$item->save();
}
} else {
// Get item
$item = FileManagerFile::onlyTrashed()
->where('user_id', $user_id)
->where('unique_id', $restore_item['unique_id'])
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->folder_id = 0;
$item->save();
}
}
} else {
// Get item
$item = FileManagerFile::onlyTrashed()
->where('user_id', $user_id)
->where('unique_id', $unique_id)
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->folder_id = 0;
$item->save();
}
// Restore Item
$item->restore();
}
// Restore Item
$item->restore();
// Return response
return response('Done!', 204);
}
@@ -466,19 +466,16 @@ class SetupWizardController extends Controller
]);
// Create legal pages and index content
if ($request->license === 'Extended') {
$pages = collect(config('content.pages'));
$content = $request->license === 'Extended' ? collect(config('content.content_extended')) : collect(config('content.content_regular'));
$pages = collect(config('content.pages'));
$content = collect(config('content.content'));
$content->each(function ($content) {
Setting::updateOrCreate($content);
});
$content->each(function ($content) {
Setting::updateOrCreate($content);
});
$pages->each(function ($page) {
Page::updateOrCreate($page);
});
}
$pages->each(function ($page) {
Page::updateOrCreate($page);
});
// Retrieve access token
$response = Route::dispatch(self::make_login_request($request));
@@ -11,119 +11,6 @@ use Schema;
class UpgradeAppController extends Controller
{
/**
* Upgrade account from 1.6 to 1.7
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function upgrade(Request $request)
{
$upgraded = Setting::where('name', 'latest_upgrade')->first();
if ($upgraded && $upgraded->value === '1.7') abort(401);
// Create legal pages and index content
if ($request->license === 'Extended') {
$pages = collect(config('content.pages'));
$content = collect(config('content.content'));
$content->each(function ($content) {
Setting::updateOrCreate($content);
});
$pages->each(function ($page) {
Page::updateOrCreate($page);
});
}
// Store Logo
if ($request->hasFile('logo')) {
$logo = store_system_image($request->file('logo'), 'system');
}
// Store Logo horizontal
if ($request->hasFile('logo_horizontal')) {
$logo_horizontal = store_system_image($request->file('logo_horizontal'), 'system');
}
// Store favicon
if ($request->hasFile('favicon')) {
$favicon = store_system_image($request->file('favicon'), 'system');
}
// Get options
$settings = collect([
[
'name' => 'setup_wizard_database',
'value' => 1,
],
[
'name' => 'setup_wizard_success',
'value' => 1,
],
[
'name' => 'license',
'value' => $request->license,
],
[
'name' => 'purchase_code',
'value' => $request->purchase_code,
],
[
'name' => 'app_title',
'value' => $request->title,
],
[
'name' => 'app_description',
'value' => $request->description,
],
[
'name' => 'app_logo',
'value' => $request->hasFile('logo') ? $logo : null,
],
[
'name' => 'app_logo_horizontal',
'value' => $request->hasFile('logo_horizontal') ? $logo_horizontal : null,
],
[
'name' => 'app_favicon',
'value' => $request->hasFile('favicon') ? $favicon : null,
],
[
'name' => 'google_analytics',
'value' => $request->googleAnalytics,
],
[
'name' => 'contact_email',
'value' => $request->contactMail,
],
[
'name' => 'registration',
'value' => $request->userRegistration,
],
[
'name' => 'storage_limitation',
'value' => $request->storageLimitation,
],
[
'name' => 'storage_default',
'value' => $request->defaultStorage ? $request->defaultStorage : 5,
],
[
'name' => 'latest_upgrade',
'value' => '1.7',
],
]);
// Store options
$settings->each(function ($col) {
Setting::updateOrCreate(['name' => $col['name']], $col);
});
return response('Done', 200);
}
/**
* Start maintenance mode
@@ -150,8 +37,33 @@ class UpgradeAppController extends Controller
/**
* Upgrade database
*/
public function upgrade_database()
public function upgrade()
{
/*
* Upgrade user_settings & file_manager_folders table
*
* @since v1.8.1
*/
if (! Schema::hasColumn('user_settings', 'timezone') && ! Schema::hasColumn('file_manager_folders', 'icon_color')) {
$this->upgrade_database();
// Create legal pages and index content for regular license
if (get_setting('license') === 'Regular') {
$pages = collect(config('content.pages'));
$content = collect(config('content.content_regular'));
$content->each(function ($content) {
Setting::updateOrCreate($content);
});
$pages->each(function ($page) {
Page::updateOrCreate($page);
});
}
}
/*
* Upgrade expire_in in shares table
*
@@ -159,17 +71,16 @@ class UpgradeAppController extends Controller
*/
if (! Schema::hasTable('traffic') && ! Schema::hasTable('zips') && ! Schema::hasTable('jobs')) {
$command = Artisan::call('migrate', [
'--force' => true
]);
$this->upgrade_database();
}
/*
* Upgrade expire_in in shares table
*
* @since v1.8
*/
if (! Schema::hasTable('traffic') && ! Schema::hasTable('zips') && ! Schema::hasTable('jobs')) {
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
$this->upgrade_database();
}
/*
@@ -179,17 +90,7 @@ class UpgradeAppController extends Controller
*/
if (! Schema::hasColumn('shares', 'expire_in')) {
$command = Artisan::call('migrate', [
'--force' => true
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
$this->upgrade_database();
}
/*
@@ -199,17 +100,26 @@ class UpgradeAppController extends Controller
*/
if (! Schema::hasColumn('file_manager_files', 'metadata')) {
$command = Artisan::call('migrate', [
'--force' => true
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
$this->upgrade_database();
}
}
/**
* @return int|mixed
*/
private function upgrade_database()
{
$command = Artisan::call('migrate', [
'--force' => true
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
return $command;
}
}
+70 -1
View File
@@ -2,6 +2,7 @@
use App\FileManagerFile;
use App\FileManagerFolder;
use App\User;
use App\Setting;
use App\Share;
use ByteUnits\Metric;
@@ -558,7 +559,17 @@ function get_pretty_name($basename, $name, $mimetype)
function get_image_meta_data($file)
{
if (get_file_type_from_mimetype($file->getMimeType()) === 'jpeg') {
return exif_read_data($file);
try {
// Try to get the exif data
return mb_convert_encoding(Image::make($file->getRealPath())->exif(),'UTF8', 'UTF8');
} catch ( \Exception $e) {
return null;
}
}
}
@@ -733,3 +744,61 @@ function remove_accents($string) {
return $string;
}
/**
* Get all files from folder and get their folder location in VueFileManager directories
*
* @param $folders
* @param null $files
* @param array $path
* @return array
*/
function get_files_for_zip($folders, $files, $path = [])
{
// Return file list
if (!isset($folders->folders)) {
return $files->unique()->values()->all();
}
// Push file path
array_push($path, $folders->name);
// Push file to collection
$folders->files->each(function ($file) use ($files, $path) {
$files->push([
'name' => $file->name,
'basename' => $file->basename,
'folder_path' => implode('/', $path),
]);
});
// Get all children folders and folders within
if ($folders->folders->isNotEmpty()) {
$folders->folders->map(function ($folder) use ($files, $path) {
return get_files_for_zip($folder, $files, $path);
});
}
return get_files_for_zip($folders->folders->first(), $files, $path);
}
/**
* Set time by user timezone GMT
*
* @param $time
* @return int
*/
function set_time_by_user_timezone($time)
{
$user = Auth::user();
if($user) {
// Get the value of timezone if user have some
$time_zone = intval($user->settings->timezone * 60 ?? null);
return Carbon::parse($time)->addMinutes($time_zone ?? null);
}
return Carbon::parse($time);
}
@@ -31,6 +31,7 @@ class CreateShareRequest extends FormRequest
'expiration' => 'integer|nullable',
'permission' => 'string',
'password' => 'string',
'emails.*' => 'email'
];
}
}
+10 -1
View File
@@ -76,7 +76,16 @@ class UserResource extends JsonResource
'folders' => $this->folder_tree
],
],
]
],
'timezone' => [
'data' => [
'id' => '1',
'type' => 'timezone',
'attributes' => [
'timezone' =>$this->settings->timezone
],
]
],
]
];
}
+111 -1
View File
@@ -26,6 +26,116 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
class Editor
{
/**
* Store folder icon
*
* @param $folder_icon
* @param $unique_id
* @param $shared
*/
public static function set_folder_icon ($folder_icon, $unique_id, $shared = null)
{
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
// Get folder
$folder = FileManagerFolder::where('user_id', $user_id)
->where('unique_id', $unique_id)
->first();
// If request have emoji set folder icon emoji
if(isset($folder_icon['emoji'])) {
$folder->icon_emoji = $folder_icon['emoji'];
$folder->icon_color = null;
}
// If request have color set folder icon color
if(isset($folder_icon['color'])) {
$folder->icon_emoji = null;
$folder->icon_color = $folder_icon['color'];
}
// Save changes
$folder->save();
}
/**
* Zip requested folder
*
* @param $unique_id
* @param $shared
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public static function zip_folder($unique_id, $shared = null)
{
// Get folder
$requested_folder = FileManagerFolder::with(['folders.files', 'files'])
->where('unique_id', $unique_id)
->where('user_id', Auth::id() ?? $shared->user_id)
->with('folders')
->first();
$files = get_files_for_zip($requested_folder, collect([]));
// Local storage instance
$disk_local = Storage::disk('local');
// Create zip directory
if (!$disk_local->exists('zip')) {
$disk_local->makeDirectory('zip');
}
// Move file to local storage
if (!is_storage_driver('local')) {
// Create temp directory
if (!$disk_local->exists('temp')) {
$disk_local->makeDirectory('temp');
}
foreach ($files as $file) {
try {
$disk_local->put('temp/' . $file['basename'], Storage::get('file-manager/' . $file['basename']));
} catch (FileNotFoundException $e) {
throw new HttpException(404, 'File not found');
}
}
}
// Get zip path
$zip_name = Str::random(16) . '-' . Str::slug($requested_folder->name) . '.zip';
$zip_path = 'zip/' . $zip_name;
// Create zip
$zip = Madzipper::make(storage_path() . '/app/' . $zip_path);
// Get files folder on local storage drive
$files_folder = is_storage_driver('local') ? 'file-manager' : 'temp';
// Add files to zip
foreach ($files as $file) {
$zip->folder($file['folder_path'])->addString($file['name'], File::get(storage_path() . '/app/' . $files_folder . '/' . $file['basename']));
}
// Close zip
$zip->close();
// Delete temporary files
if (!is_storage_driver('local')) {
foreach ($files as $file) {
$disk_local->delete('temp/' . $file['basename']);
}
}
// Store zip record
return Zip::create([
'user_id' => $shared->user_id ?? Auth::id(),
'shared_token' => $shared->token ?? null,
'basename' => $zip_name,
]);
}
/**
* Zip selected files, store it in /zip folder and retrieve zip record
@@ -329,7 +439,7 @@ class Editor
$temp_filename = $file->getClientOriginalName();
// File Path
$file_path = config('filesystems.disks.local.root') . '/chunks/' . $temp_filename;\
$file_path = config('filesystems.disks.local.root') . '/chunks/' . $temp_filename;
// Generate file
File::append($file_path, $file->get());