mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
Transfer Content Ownership To Team Folder Owner
This commit is contained in:
@@ -59,7 +59,7 @@
|
||||
"/chunks/plans.js": "/chunks/plans.js?id=6fca685daa45f22e4c8f",
|
||||
"/chunks/platform.js": "/chunks/platform.js?id=1863e0b77ad5c26a05bc",
|
||||
"/chunks/platform~chunks/settings-subscription~chunks/shared~chunks/user-subscription.js": "/chunks/platform~chunks/settings-subscription~chunks/shared~chunks/user-subscription.js?id=8656b69a97cace919251",
|
||||
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=1bb410d04a3fb0bdd15c",
|
||||
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=f0d10b45321b77d9fb21",
|
||||
"/chunks/profile.js": "/chunks/profile.js?id=022c1617a575d4aab4e1",
|
||||
"/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=58edfb3a35062e1ba4e0",
|
||||
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=f8b2619e393a5823bf29",
|
||||
@@ -1488,5 +1488,13 @@
|
||||
"/chunks/shared-with-me.93d1862a2d1291f017c5.hot-update.js": "/chunks/shared-with-me.93d1862a2d1291f017c5.hot-update.js",
|
||||
"/chunks/team-folders.5f3b12c7626c1febc1f4.hot-update.js": "/chunks/team-folders.5f3b12c7626c1febc1f4.hot-update.js",
|
||||
"/chunks/team-folders.9a710c5840f0fe78b845.hot-update.js": "/chunks/team-folders.9a710c5840f0fe78b845.hot-update.js",
|
||||
"/chunks/shared-with-me.de7b0068aa7d3daa54d0.hot-update.js": "/chunks/shared-with-me.de7b0068aa7d3daa54d0.hot-update.js"
|
||||
"/chunks/shared-with-me.de7b0068aa7d3daa54d0.hot-update.js": "/chunks/shared-with-me.de7b0068aa7d3daa54d0.hot-update.js",
|
||||
"/js/main.b96dce782e1445910175.hot-update.js": "/js/main.b96dce782e1445910175.hot-update.js",
|
||||
"/js/main.d367944ae8ff81bdfd36.hot-update.js": "/js/main.d367944ae8ff81bdfd36.hot-update.js",
|
||||
"/js/main.8e230d654f8e6dc09627.hot-update.js": "/js/main.8e230d654f8e6dc09627.hot-update.js",
|
||||
"/js/main.254907f280bbbbaaa3cf.hot-update.js": "/js/main.254907f280bbbbaaa3cf.hot-update.js",
|
||||
"/chunks/platform~chunks/shared.f81c519d38811aa1937b.hot-update.js": "/chunks/platform~chunks/shared.f81c519d38811aa1937b.hot-update.js",
|
||||
"/chunks/platform~chunks/shared.1b7dcdcf4abc08a8b218.hot-update.js": "/chunks/platform~chunks/shared.1b7dcdcf4abc08a8b218.hot-update.js",
|
||||
"/chunks/platform~chunks/shared.61307263989bd7deb32e.hot-update.js": "/chunks/platform~chunks/shared.61307263989bd7deb32e.hot-update.js",
|
||||
"/chunks/platform~chunks/shared.3f8787077c840fc65667.hot-update.js": "/chunks/platform~chunks/shared.3f8787077c840fc65667.hot-update.js"
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
:title="$t('Author')"
|
||||
>
|
||||
<div class="flex items-center mt-1">
|
||||
<MemberAvatar :size="32" :member="singleFile.data.relationships.user" />
|
||||
<span class="ml-2 block">{{ singleFile.data.relationships.user.data.attributes.name }}</span>
|
||||
<MemberAvatar :size="32" :member="singleFile.data.relationships.owner" />
|
||||
<span class="ml-2 block">{{ singleFile.data.relationships.owner.data.attributes.name }}</span>
|
||||
</div>
|
||||
</ListInfoItem>
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
canShowAuthor() {
|
||||
return this.$isThisRoute(this.$route, ['SharedWithMe', 'TeamFolders'])
|
||||
&& this.clipboard[0].data.type !== 'folder'
|
||||
&& this.user.data.id !== this.clipboard[0].data.relationships.user.data.id
|
||||
&& this.user.data.id !== this.clipboard[0].data.relationships.owner.data.id
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
2
resources/js/helpers/itemHelpers.js
vendored
2
resources/js/helpers/itemHelpers.js
vendored
@@ -48,7 +48,7 @@ const itemHelpers = {
|
||||
Vue.prototype.$detachMeFromTeamFolder = function (folder) {
|
||||
events.$emit('confirm:open', {
|
||||
title: this.$t('Are you sure you want to leave this team?'),
|
||||
message: this.$t('You will not have access to the files in this team folder.'),
|
||||
message: this.$t("You will don't have access to the files and all your previously uploaded content will be part of this Team Folder you are leaving."),
|
||||
action: {
|
||||
id: folder.data.id,
|
||||
operation: 'leave-team-folder',
|
||||
|
||||
@@ -17,7 +17,7 @@ class SetTeamFolderPropertyForAllChildrenAction
|
||||
|
||||
// Set all children as team_folder = true
|
||||
DB::table('folders')
|
||||
->whereIn('id', Arr::flatten([filter_folders_ids($childrenFolderIds)]))
|
||||
->whereIn('id', Arr::flatten(filter_folders_ids($childrenFolderIds)))
|
||||
->update(['team_folder' => $isTeamFolder]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Teams\Actions;
|
||||
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class TransferContentOwnershipToTeamFolderOwnerAction
|
||||
{
|
||||
public function __invoke(Folder $folder, $leavingUserId)
|
||||
{
|
||||
// Find and delete attached member from team folder
|
||||
DB::table('team_folder_members')
|
||||
->where('parent_id', $folder->id)
|
||||
->where('user_id', $leavingUserId)
|
||||
->delete();
|
||||
|
||||
// Get all inherited folder from team folder
|
||||
$childrenFolderIds = Folder::with('folders:id,parent_id')
|
||||
->where('id', $folder->id)
|
||||
->get('id');
|
||||
|
||||
$teamFolderIds = Arr::flatten(filter_folders_ids($childrenFolderIds));
|
||||
|
||||
// Replace leaver content ownership for author of team folder
|
||||
DB::table('files')
|
||||
->whereIn('parent_id', $teamFolderIds)
|
||||
->where('user_id', $leavingUserId)
|
||||
->cursor()
|
||||
->each(fn ($file) =>
|
||||
$this->move_files_to_the_new_destination($file, $folder)
|
||||
);
|
||||
|
||||
DB::table('files')
|
||||
->whereIn('parent_id', $teamFolderIds)
|
||||
->where('user_id', $leavingUserId)
|
||||
->update(['user_id' => $folder->user_id]);
|
||||
|
||||
DB::table('folders')
|
||||
->whereIn('id', $teamFolderIds)
|
||||
->where('user_id', $leavingUserId)
|
||||
->update(['user_id' => $folder->user_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @param Folder $folder
|
||||
*/
|
||||
private function move_files_to_the_new_destination($file, Folder $folder): void
|
||||
{
|
||||
// Move image thumbnails
|
||||
if ($file->type === 'image') {
|
||||
|
||||
// Get image thumbnail list
|
||||
$thumbnailList = get_thumbnail_file_list($file->basename);
|
||||
|
||||
// move thumbnails to the new location
|
||||
$thumbnailList->each(function ($basename) use ($file, $folder) {
|
||||
|
||||
$oldPath = "files/$file->user_id/$basename";
|
||||
$newPath = "files/$folder->user_id/$basename";
|
||||
|
||||
if (Storage::exists($oldPath)) Storage::move($oldPath, $newPath);
|
||||
});
|
||||
}
|
||||
|
||||
// Move single file
|
||||
Storage::move("files/$file->user_id/$file->basename", "files/$folder->user_id/$file->basename");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use Domain\Folders\Models\Folder;
|
||||
|
||||
class UpdateMembersAction
|
||||
{
|
||||
// TODO: after removing user from team folder from administrator, set file owner
|
||||
public function __invoke(Folder $folder, $members): void
|
||||
{
|
||||
$existingMembers = $folder
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Teams\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Gate;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Domain\Teams\Actions\TransferContentOwnershipToTeamFolderOwnerAction;
|
||||
|
||||
class LeaveTeamFolderController extends Controller
|
||||
{
|
||||
public function __invoke(Folder $folder): Response | Application | ResponseFactory
|
||||
public function __construct(
|
||||
public TransferContentOwnershipToTeamFolderOwnerAction $transferContentOwnership,
|
||||
) {}
|
||||
|
||||
public function __invoke(Folder $folder): Response|Application|ResponseFactory
|
||||
{
|
||||
// Find and delete attached member from team folder
|
||||
DB::table('team_folder_members')
|
||||
->where('parent_id', $folder->id)
|
||||
->where('user_id', Auth::id())
|
||||
->delete();
|
||||
// Authorize action
|
||||
if (! Gate::any(['can-edit', 'can-view'], [$folder, null])) {
|
||||
abort(403, 'Access Denied');
|
||||
}
|
||||
|
||||
// Transfer files/folders ownership to team folder owner
|
||||
($this->transferContentOwnership)($folder, Auth::id());
|
||||
|
||||
return response('Done.', 204);
|
||||
}
|
||||
|
||||
@@ -599,6 +599,17 @@ if (! function_exists('get_file_type')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('get_thumbnail_file_list')) {
|
||||
/**
|
||||
* Get list of image thumbnails
|
||||
*/
|
||||
function get_thumbnail_file_list(string $basename): Collection
|
||||
{
|
||||
return collect(config('vuefilemanager.image_sizes'))
|
||||
->map(fn ($item) => $item['name'] . '-' . $basename);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('map_language_translations')) {
|
||||
/**
|
||||
* It map language translations as language key and language value
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace Tests\Domain\Teams;
|
||||
|
||||
use Domain\Files\Models\File;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Str;
|
||||
use Notification;
|
||||
use Tests\TestCase;
|
||||
@@ -574,10 +577,62 @@ class TeamManagementTest extends TestCase
|
||||
|
||||
$folder = Folder::factory()
|
||||
->create([
|
||||
'name' => 'Team Folder',
|
||||
'user_id' => $user->id,
|
||||
'team_folder' => 1,
|
||||
]);
|
||||
|
||||
$folderWithin = Folder::factory()
|
||||
->create([
|
||||
'name' => 'Member Content',
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $member->id,
|
||||
'team_folder' => 1,
|
||||
]);
|
||||
|
||||
$file = File::factory()
|
||||
->create([
|
||||
'name' => 'Member File',
|
||||
'basename' => 'fake-file.zip',
|
||||
'parent_id' => $folderWithin->id,
|
||||
'user_id' => $member->id,
|
||||
'type' => 'file',
|
||||
]);
|
||||
|
||||
// Create fake file
|
||||
$fakeFile = UploadedFile::fake()
|
||||
->create('fake-file.zip', 2000, 'application/zip');
|
||||
|
||||
// Put fake file into correct directory
|
||||
Storage::putFileAs("files/$member->id", $fakeFile, 'fake-file.zip');
|
||||
|
||||
File::factory()
|
||||
->create([
|
||||
'name' => 'Good image',
|
||||
'basename' => 'fake-image.jpeg',
|
||||
'parent_id' => $folderWithin->id,
|
||||
'user_id' => $member->id,
|
||||
'type' => 'image',
|
||||
]);
|
||||
|
||||
// Create fake image
|
||||
$fakeFile = UploadedFile::fake()
|
||||
->create("fake-image.jpeg", 2000, 'image/jpeg');
|
||||
|
||||
// Put fake image into correct directory
|
||||
Storage::putFileAs("files/$member->id", $fakeFile, $fakeFile->name);
|
||||
|
||||
// Create fake image thumbnails
|
||||
collect(config('vuefilemanager.image_sizes'))
|
||||
->each(function ($item) use ($member) {
|
||||
|
||||
$fakeFile = UploadedFile::fake()
|
||||
->create("{$item['name']}-fake-image.jpeg", 2000, 'image/jpeg');
|
||||
|
||||
Storage::putFileAs("files/$member->id", $fakeFile, $fakeFile->name);
|
||||
});
|
||||
|
||||
// add member to the team folder
|
||||
DB::table('team_folder_members')
|
||||
->insert([
|
||||
[
|
||||
@@ -592,11 +647,31 @@ class TeamManagementTest extends TestCase
|
||||
->deleteJson("/api/teams/folders/{$folder->id}/leave")
|
||||
->assertNoContent();
|
||||
|
||||
// Check if file was moved from member directory to owner directory
|
||||
Storage::assertMissing("files/$member->id/fake-file.zip");
|
||||
Storage::assertExists("files/$user->id/fake-file.zip");
|
||||
|
||||
// Assert if image thumbnails was moved correctly to the new destination
|
||||
collect(config('vuefilemanager.image_sizes'))
|
||||
->each(function ($item) use ($user) {
|
||||
Storage::assertExists("files/$user->id/{$item['name']}-fake-image.jpeg");
|
||||
});
|
||||
|
||||
$this
|
||||
->assertDatabaseMissing('team_folder_members', [
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $member->id,
|
||||
'permission' => 'can-edit',
|
||||
])
|
||||
->assertDatabaseHas('files', [
|
||||
'id' => $file->id,
|
||||
'parent_id' => $folderWithin->id,
|
||||
'user_id' => $user->id,
|
||||
])
|
||||
->assertDatabaseHas('folders', [
|
||||
'id' => $folderWithin->id,
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user