diff --git a/client/src/app/+admin/overview/videos/video-list.component.html b/client/src/app/+admin/overview/videos/video-list.component.html index 06b9ab347..14bbb55e9 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.html +++ b/client/src/app/+admin/overview/videos/video-list.component.html @@ -109,6 +109,7 @@ {{ file.resolution.label }}: {{ file.size | bytes: 1 }} @@ -124,6 +125,7 @@ {{ file.resolution.label }}: {{ file.size | bytes: 1 }} diff --git a/client/src/app/+admin/overview/videos/video-list.component.ts b/client/src/app/+admin/overview/videos/video-list.component.ts index ed7ec54a1..cb693ce12 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.ts +++ b/client/src/app/+admin/overview/videos/video-list.component.ts @@ -166,6 +166,10 @@ export class VideoListComponent extends RestTable implements OnInit { return video.files.length !== 0 } + canRemoveOneFile (video: Video) { + return video.canRemoveOneFile(this.authUser) + } + getFilesSize (video: Video) { let files = video.files diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts index 2e4ab87d7..c9c6b979c 100644 --- a/client/src/app/shared/shared-main/video/video.model.ts +++ b/client/src/app/shared/shared-main/video/video.model.ts @@ -1,8 +1,8 @@ import { AuthUser } from '@app/core' import { User } from '@app/core/users/user.model' -import { durationToString, prepareIcu, getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers' +import { durationToString, getAbsoluteAPIUrl, getAbsoluteEmbedUrl, prepareIcu } from '@app/helpers' import { Actor } from '@app/shared/shared-main/account/actor.model' -import { buildVideoWatchPath } from '@shared/core-utils' +import { buildVideoWatchPath, getAllFiles } from '@shared/core-utils' import { peertubeTranslate } from '@shared/core-utils/i18n' import { ActorImage, @@ -240,6 +240,13 @@ export class Video implements VideoServerModel { return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.SEE_ALL_VIDEOS)) } + canRemoveOneFile (user: AuthUser) { + return this.isLocal && + user && user.hasRight(UserRight.MANAGE_VIDEO_FILES) && + this.state.id !== VideoState.TO_TRANSCODE && + getAllFiles(this).length > 1 + } + canRemoveFiles (user: AuthUser) { return this.isLocal && user && user.hasRight(UserRight.MANAGE_VIDEO_FILES) && diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts index 48982f4de..885751285 100644 --- a/server/tests/api/live/live.ts +++ b/server/tests/api/live/live.ts @@ -3,8 +3,8 @@ import { expect } from 'chai' import { basename, join } from 'path' import { ffprobePromise, getVideoStream } from '@server/helpers/ffmpeg' -import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist, getAllFiles, testImage } from '@server/tests/shared' -import { wait } from '@shared/core-utils' +import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist, testImage } from '@server/tests/shared' +import { getAllFiles, wait } from '@shared/core-utils' import { HttpStatusCode, LiveVideo, diff --git a/server/tests/api/transcoding/transcoder.ts b/server/tests/api/transcoding/transcoder.ts index db0127805..c591f5f6f 100644 --- a/server/tests/api/transcoding/transcoder.ts +++ b/server/tests/api/transcoding/transcoder.ts @@ -2,8 +2,8 @@ import { expect } from 'chai' import { canDoQuickTranscode } from '@server/helpers/ffmpeg' -import { generateHighBitrateVideo, generateVideoWithFramerate, getAllFiles } from '@server/tests/shared' -import { buildAbsoluteFixturePath, getMaxBitrate, getMinLimitBitrate, omit } from '@shared/core-utils' +import { generateHighBitrateVideo, generateVideoWithFramerate } from '@server/tests/shared' +import { buildAbsoluteFixturePath, getAllFiles, getMaxBitrate, getMinLimitBitrate, omit } from '@shared/core-utils' import { buildFileMetadata, getAudioStream, diff --git a/server/tests/api/transcoding/video-studio.ts b/server/tests/api/transcoding/video-studio.ts index ac1c0fc7e..9613111b5 100644 --- a/server/tests/api/transcoding/video-studio.ts +++ b/server/tests/api/transcoding/video-studio.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { expectStartWith, getAllFiles } from '@server/tests/shared' -import { areObjectStorageTestsDisabled } from '@shared/core-utils' +import { expectStartWith } from '@server/tests/shared' +import { areObjectStorageTestsDisabled, getAllFiles } from '@shared/core-utils' import { VideoStudioTask } from '@shared/models' import { cleanupTests, diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts index 53c4e7824..97632450a 100644 --- a/server/tests/cli/update-host.ts +++ b/server/tests/cli/update-host.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ import { expect } from 'chai' +import { getAllFiles } from '@shared/core-utils' import { cleanupTests, createSingleServer, @@ -11,7 +12,6 @@ import { setAccessTokensToServers, waitJobs } from '@shared/server-commands' -import { getAllFiles } from '../shared' describe('Test update host scripts', function () { let server: PeerTubeServer diff --git a/server/tests/shared/videos.ts b/server/tests/shared/videos.ts index 3ab245392..e18329e07 100644 --- a/server/tests/shared/videos.ts +++ b/server/tests/shared/videos.ts @@ -241,16 +241,6 @@ async function uploadRandomVideoOnServers ( return res } -function getAllFiles (video: VideoDetails) { - const files = video.files - - if (video.streamingPlaylists[0]) { - return files.concat(video.streamingPlaylists[0].files) - } - - return files -} - // --------------------------------------------------------------------------- export { @@ -258,6 +248,5 @@ export { checkUploadVideoParam, uploadRandomVideoOnServers, checkVideoFilesWereRemoved, - saveVideoInServers, - getAllFiles + saveVideoInServers } diff --git a/shared/core-utils/videos/privacy.ts b/shared/core-utils/videos/privacy.ts index 7d3b67d50..f33487b49 100644 --- a/shared/core-utils/videos/privacy.ts +++ b/shared/core-utils/videos/privacy.ts @@ -1,9 +1,21 @@ +import { VideoDetails } from '../../models/videos/video.model' import { VideoPrivacy } from '../../models/videos/video-privacy.enum' function getAllPrivacies () { return [ VideoPrivacy.PUBLIC, VideoPrivacy.INTERNAL, VideoPrivacy.PRIVATE, VideoPrivacy.UNLISTED ] } -export { - getAllPrivacies +function getAllFiles (video: Partial>) { + const files = video.files + + if (video.streamingPlaylists[0]) { + return files.concat(video.streamingPlaylists[0].files) + } + + return files +} + +export { + getAllPrivacies, + getAllFiles }