Add ability to filter out public videos from admin
This commit is contained in:
parent
8f2608e9a9
commit
527a52ac42
15 changed files with 125 additions and 30 deletions
|
@ -5,7 +5,8 @@ import { Injectable } from '@angular/core'
|
|||
import { RestExtractor, RestPagination, RestService } from '@app/core'
|
||||
import { AdvancedInputFilter } from '@app/shared/shared-forms'
|
||||
import { CommonVideoParams, Video, VideoService } from '@app/shared/shared-main'
|
||||
import { ResultList, VideoInclude } from '@shared/models'
|
||||
import { ResultList, VideoInclude, VideoPrivacy } from '@shared/models'
|
||||
import { getAllPrivacies } from '@shared/core-utils'
|
||||
|
||||
@Injectable()
|
||||
export class VideoAdminService {
|
||||
|
@ -96,6 +97,10 @@ export class VideoAdminService {
|
|||
{
|
||||
value: 'excludeMuted',
|
||||
label: $localize`Exclude muted accounts`
|
||||
},
|
||||
{
|
||||
value: 'excludePublic',
|
||||
label: $localize`Exclude public videos`
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -105,11 +110,12 @@ export class VideoAdminService {
|
|||
private buildAdminParamsFromSearch (search: string, params: HttpParams) {
|
||||
let include = VideoInclude.BLACKLISTED |
|
||||
VideoInclude.BLOCKED_OWNER |
|
||||
VideoInclude.HIDDEN_PRIVACY |
|
||||
VideoInclude.NOT_PUBLISHED_STATE |
|
||||
VideoInclude.FILES
|
||||
|
||||
if (!search) return this.restService.addObjectParams(params, { include })
|
||||
let privacyOneOf = getAllPrivacies()
|
||||
|
||||
if (!search) return this.restService.addObjectParams(params, { include, privacyOneOf })
|
||||
|
||||
const filters = this.restService.parseQueryStringFilter(search, {
|
||||
isLocal: {
|
||||
|
@ -131,6 +137,10 @@ export class VideoAdminService {
|
|||
excludeMuted: {
|
||||
prefix: 'excludeMuted',
|
||||
handler: () => true
|
||||
},
|
||||
excludePublic: {
|
||||
prefix: 'excludePublic',
|
||||
handler: () => true
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -140,6 +150,12 @@ export class VideoAdminService {
|
|||
filters.excludeMuted = undefined
|
||||
}
|
||||
|
||||
return this.restService.addObjectParams(params, { ...filters, include })
|
||||
if (filters.excludePublic) {
|
||||
privacyOneOf = [ VideoPrivacy.PRIVATE, VideoPrivacy.UNLISTED, VideoPrivacy.INTERNAL ]
|
||||
|
||||
filters.excludePublic = undefined
|
||||
}
|
||||
|
||||
return this.restService.addObjectParams(params, { ...filters, include, privacyOneOf })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ export type CommonVideoParams = {
|
|||
isLocal?: boolean
|
||||
categoryOneOf?: number[]
|
||||
languageOneOf?: string[]
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
isLive?: boolean
|
||||
skipCount?: boolean
|
||||
|
||||
|
@ -392,6 +393,7 @@ export class VideoService {
|
|||
include,
|
||||
categoryOneOf,
|
||||
languageOneOf,
|
||||
privacyOneOf,
|
||||
skipCount,
|
||||
nsfwPolicy,
|
||||
isLive,
|
||||
|
@ -413,6 +415,7 @@ export class VideoService {
|
|||
if (nsfwPolicy) newParams = newParams.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy))
|
||||
if (languageOneOf) newParams = this.restService.addArrayParams(newParams, 'languageOneOf', languageOneOf)
|
||||
if (categoryOneOf) newParams = this.restService.addArrayParams(newParams, 'categoryOneOf', categoryOneOf)
|
||||
if (privacyOneOf) newParams = this.restService.addArrayParams(newParams, 'privacyOneOf', privacyOneOf)
|
||||
|
||||
return newParams
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { intoArray, toBoolean } from '@app/helpers'
|
||||
import { AttributesOnly } from '@shared/core-utils'
|
||||
import { BooleanBothQuery, NSFWPolicyType, VideoInclude, VideoSortField } from '@shared/models'
|
||||
import { AttributesOnly, getAllPrivacies } from '@shared/core-utils'
|
||||
import { BooleanBothQuery, NSFWPolicyType, VideoInclude, VideoPrivacy, VideoSortField } from '@shared/models'
|
||||
|
||||
type VideoFiltersKeys = {
|
||||
[ id in keyof AttributesOnly<VideoFilters> ]: any
|
||||
|
@ -198,13 +198,15 @@ export class VideoFilters {
|
|||
toVideosAPIObject () {
|
||||
let isLocal: boolean
|
||||
let include: VideoInclude
|
||||
let privacyOneOf: VideoPrivacy[]
|
||||
|
||||
if (this.scope === 'local') {
|
||||
isLocal = true
|
||||
}
|
||||
|
||||
if (this.allVideos) {
|
||||
include = VideoInclude.NOT_PUBLISHED_STATE | VideoInclude.HIDDEN_PRIVACY
|
||||
include = VideoInclude.NOT_PUBLISHED_STATE
|
||||
privacyOneOf = getAllPrivacies()
|
||||
}
|
||||
|
||||
let isLive: boolean
|
||||
|
@ -219,6 +221,7 @@ export class VideoFilters {
|
|||
search: this.search,
|
||||
isLocal,
|
||||
include,
|
||||
privacyOneOf,
|
||||
isLive
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { HttpStatusCode } from '@shared/models'
|
|||
import { root } from '../helpers/core-utils'
|
||||
import { STATIC_MAX_AGE } from '../initializers/constants'
|
||||
import { ClientHtml, sendHTML, serveIndexHTML } from '../lib/client-html'
|
||||
import { asyncMiddleware, disableRobots, embedCSP } from '../middlewares'
|
||||
import { asyncMiddleware, embedCSP } from '../middlewares'
|
||||
|
||||
const clientsRouter = express.Router()
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ function pickCommonVideoQuery (query: VideosCommonQueryAfterSanitize) {
|
|||
'categoryOneOf',
|
||||
'licenceOneOf',
|
||||
'languageOneOf',
|
||||
'privacyOneOf',
|
||||
'tagsOneOf',
|
||||
'tagsAllOf',
|
||||
'isLocal',
|
||||
|
|
|
@ -7,6 +7,7 @@ import { isAbleToUploadVideo } from '@server/lib/user'
|
|||
import { getServerActor } from '@server/models/application/application'
|
||||
import { ExpressPromiseHandler } from '@server/types/express'
|
||||
import { MUserAccountId, MVideoFullLight } from '@server/types/models'
|
||||
import { getAllPrivacies } from '@shared/core-utils'
|
||||
import { VideoInclude } from '@shared/models'
|
||||
import { ServerErrorCode, UserRight, VideoPrivacy } from '../../../../shared'
|
||||
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
|
||||
|
@ -487,6 +488,10 @@ const commonVideosFiltersValidator = [
|
|||
.optional()
|
||||
.customSanitizer(toArray)
|
||||
.custom(isStringArray).withMessage('Should have a valid one of language array'),
|
||||
query('privacyOneOf')
|
||||
.optional()
|
||||
.customSanitizer(toArray)
|
||||
.custom(isNumberArray).withMessage('Should have a valid one of privacy array'),
|
||||
query('tagsOneOf')
|
||||
.optional()
|
||||
.customSanitizer(toArray)
|
||||
|
@ -536,10 +541,12 @@ const commonVideosFiltersValidator = [
|
|||
// FIXME: deprecated in 4.0, to remove
|
||||
{
|
||||
if (req.query.filter === 'all-local') {
|
||||
req.query.include = VideoInclude.NOT_PUBLISHED_STATE | VideoInclude.HIDDEN_PRIVACY
|
||||
req.query.include = VideoInclude.NOT_PUBLISHED_STATE
|
||||
req.query.isLocal = true
|
||||
req.query.privacyOneOf = getAllPrivacies()
|
||||
} else if (req.query.filter === 'all') {
|
||||
req.query.include = VideoInclude.NOT_PUBLISHED_STATE | VideoInclude.HIDDEN_PRIVACY
|
||||
req.query.include = VideoInclude.NOT_PUBLISHED_STATE
|
||||
req.query.privacyOneOf = getAllPrivacies()
|
||||
} else if (req.query.filter === 'local') {
|
||||
req.query.isLocal = true
|
||||
}
|
||||
|
@ -550,7 +557,7 @@ const commonVideosFiltersValidator = [
|
|||
const user = res.locals.oauth?.token.User
|
||||
|
||||
if ((!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) !== true)) {
|
||||
if (req.query.include) {
|
||||
if (req.query.include || req.query.privacyOneOf) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.UNAUTHORIZED_401,
|
||||
message: 'You are not allowed to see all videos.'
|
||||
|
|
|
@ -40,6 +40,7 @@ export type BuildVideosListQueryOptions = {
|
|||
languageOneOf?: string[]
|
||||
tagsOneOf?: string[]
|
||||
tagsAllOf?: string[]
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
|
||||
uuids?: string[]
|
||||
|
||||
|
@ -138,11 +139,6 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
|
|||
this.whereStateAvailable()
|
||||
}
|
||||
|
||||
// Only list videos with the appropriate priavcy
|
||||
if (!(options.include & VideoInclude.HIDDEN_PRIVACY)) {
|
||||
this.wherePrivacyAvailable(options.user)
|
||||
}
|
||||
|
||||
if (options.videoPlaylistId) {
|
||||
this.joinPlaylist(options.videoPlaylistId)
|
||||
}
|
||||
|
@ -187,6 +183,13 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
|
|||
this.whereTagsAllOf(options.tagsAllOf)
|
||||
}
|
||||
|
||||
if (options.privacyOneOf) {
|
||||
this.wherePrivacyOneOf(options.privacyOneOf)
|
||||
} else {
|
||||
// Only list videos with the appropriate priavcy
|
||||
this.wherePrivacyAvailable(options.user)
|
||||
}
|
||||
|
||||
if (options.uuids) {
|
||||
this.whereUUIDs(options.uuids)
|
||||
}
|
||||
|
@ -435,6 +438,11 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
|
|||
)
|
||||
}
|
||||
|
||||
private wherePrivacyOneOf (privacyOneOf: VideoPrivacy[]) {
|
||||
this.and.push('"video"."privacy" IN (:privacyOneOf)')
|
||||
this.replacements.privacyOneOf = privacyOneOf
|
||||
}
|
||||
|
||||
private whereUUIDs (uuids: string[]) {
|
||||
this.and.push('"video"."uuid" IN (' + createSafeIn(this.sequelize, uuids) + ')')
|
||||
}
|
||||
|
|
|
@ -1041,6 +1041,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
languageOneOf?: string[]
|
||||
tagsOneOf?: string[]
|
||||
tagsAllOf?: string[]
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
|
||||
accountId?: number
|
||||
videoChannelId?: number
|
||||
|
@ -1059,6 +1060,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
search?: string
|
||||
}) {
|
||||
VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user)
|
||||
VideoModel.throwIfPrivacyOneOfWithoutUser(options.privacyOneOf, options.user)
|
||||
|
||||
const trendingDays = options.sort.endsWith('trending')
|
||||
? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS
|
||||
|
@ -1082,6 +1084,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
'languageOneOf',
|
||||
'tagsOneOf',
|
||||
'tagsAllOf',
|
||||
'privacyOneOf',
|
||||
'isLocal',
|
||||
'include',
|
||||
'displayOnlyForFollower',
|
||||
|
@ -1119,6 +1122,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
languageOneOf?: string[]
|
||||
tagsOneOf?: string[]
|
||||
tagsAllOf?: string[]
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
|
||||
displayOnlyForFollower: DisplayOnlyForFollowerOptions | null
|
||||
|
||||
|
@ -1140,6 +1144,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
uuids?: string[]
|
||||
}) {
|
||||
VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user)
|
||||
VideoModel.throwIfPrivacyOneOfWithoutUser(options.privacyOneOf, options.user)
|
||||
|
||||
const serverActor = await getServerActor()
|
||||
|
||||
|
@ -1153,6 +1158,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
'languageOneOf',
|
||||
'tagsOneOf',
|
||||
'tagsAllOf',
|
||||
'privacyOneOf',
|
||||
'user',
|
||||
'isLocal',
|
||||
'host',
|
||||
|
@ -1510,14 +1516,19 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
|||
|
||||
private static throwIfPrivateIncludeWithoutUser (include: VideoInclude, user: MUserAccountId) {
|
||||
if (VideoModel.isPrivateInclude(include) && !user?.hasRight(UserRight.SEE_ALL_VIDEOS)) {
|
||||
throw new Error('Try to filter all-local but no user has not the see all videos right')
|
||||
throw new Error('Try to filter all-local but user cannot see all videos')
|
||||
}
|
||||
}
|
||||
|
||||
private static throwIfPrivacyOneOfWithoutUser (privacyOneOf: VideoPrivacy[], user: MUserAccountId) {
|
||||
if (privacyOneOf && !user?.hasRight(UserRight.SEE_ALL_VIDEOS)) {
|
||||
throw new Error('Try to choose video privacies but user cannot see all videos')
|
||||
}
|
||||
}
|
||||
|
||||
private static isPrivateInclude (include: VideoInclude) {
|
||||
return include & VideoInclude.BLACKLISTED ||
|
||||
include & VideoInclude.BLOCKED_OWNER ||
|
||||
include & VideoInclude.HIDDEN_PRIVACY ||
|
||||
include & VideoInclude.NOT_PUBLISHED_STATE
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
setAccessTokensToServers,
|
||||
setDefaultVideoChannel
|
||||
} from '@shared/extra-utils'
|
||||
import { HttpStatusCode, UserRole, VideoInclude } from '@shared/models'
|
||||
import { HttpStatusCode, UserRole, VideoInclude, VideoPrivacy } from '@shared/models'
|
||||
|
||||
describe('Test video filters validators', function () {
|
||||
let server: PeerTubeServer
|
||||
|
@ -112,7 +112,7 @@ describe('Test video filters validators', function () {
|
|||
|
||||
const validIncludes = [
|
||||
VideoInclude.NONE,
|
||||
VideoInclude.HIDDEN_PRIVACY,
|
||||
VideoInclude.BLOCKED_OWNER,
|
||||
VideoInclude.NOT_PUBLISHED_STATE | VideoInclude.BLACKLISTED
|
||||
]
|
||||
|
||||
|
@ -120,6 +120,7 @@ describe('Test video filters validators', function () {
|
|||
token?: string
|
||||
isLocal?: boolean
|
||||
include?: VideoInclude
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
expectedStatus: HttpStatusCode
|
||||
}) {
|
||||
const paths = [
|
||||
|
@ -136,6 +137,7 @@ describe('Test video filters validators', function () {
|
|||
token: options.token || server.accessToken,
|
||||
query: {
|
||||
isLocal: options.isLocal,
|
||||
privacyOneOf: options.privacyOneOf,
|
||||
include: options.include
|
||||
},
|
||||
expectedStatus: options.expectedStatus
|
||||
|
@ -143,6 +145,22 @@ describe('Test video filters validators', function () {
|
|||
}
|
||||
}
|
||||
|
||||
it('Should fail with a bad privacyOneOf', async function () {
|
||||
await testEndpoints({ privacyOneOf: [ 'toto' ] as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
})
|
||||
|
||||
it('Should succeed with a good privacyOneOf', async function () {
|
||||
await testEndpoints({ privacyOneOf: [ VideoPrivacy.INTERNAL ], expectedStatus: HttpStatusCode.OK_200 })
|
||||
})
|
||||
|
||||
it('Should fail to use privacyOneOf with a simple user', async function () {
|
||||
await testEndpoints({
|
||||
privacyOneOf: [ VideoPrivacy.INTERNAL ],
|
||||
token: userAccessToken,
|
||||
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
|
||||
})
|
||||
})
|
||||
|
||||
it('Should fail with a bad include', async function () {
|
||||
await testEndpoints({ include: 'toto' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
})
|
||||
|
|
|
@ -138,6 +138,7 @@ describe('Test videos filter', function () {
|
|||
hasWebtorrentFiles?: boolean
|
||||
hasHLSFiles?: boolean
|
||||
include?: VideoInclude
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
category?: number
|
||||
tagsAllOf?: string[]
|
||||
token?: string
|
||||
|
@ -148,7 +149,7 @@ describe('Test videos filter', function () {
|
|||
path: options.path,
|
||||
token: options.token ?? options.server.accessToken,
|
||||
query: {
|
||||
...pick(options, [ 'isLocal', 'include', 'category', 'tagsAllOf', 'hasWebtorrentFiles', 'hasHLSFiles' ]),
|
||||
...pick(options, [ 'isLocal', 'include', 'category', 'tagsAllOf', 'hasWebtorrentFiles', 'hasHLSFiles', 'privacyOneOf' ]),
|
||||
|
||||
sort: 'createdAt'
|
||||
},
|
||||
|
@ -162,6 +163,7 @@ describe('Test videos filter', function () {
|
|||
server: PeerTubeServer
|
||||
isLocal?: boolean
|
||||
include?: VideoInclude
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
token?: string
|
||||
expectedStatus?: HttpStatusCode
|
||||
}) {
|
||||
|
@ -195,7 +197,7 @@ describe('Test videos filter', function () {
|
|||
server,
|
||||
token,
|
||||
isLocal: true,
|
||||
include: VideoInclude.HIDDEN_PRIVACY
|
||||
privacyOneOf: [ VideoPrivacy.UNLISTED, VideoPrivacy.PUBLIC, VideoPrivacy.PRIVATE ]
|
||||
})
|
||||
|
||||
for (const names of namesResults) {
|
||||
|
@ -216,7 +218,7 @@ describe('Test videos filter', function () {
|
|||
const [ channelVideos, accountVideos, videos, searchVideos ] = await getVideosNames({
|
||||
server,
|
||||
token,
|
||||
include: VideoInclude.HIDDEN_PRIVACY
|
||||
privacyOneOf: [ VideoPrivacy.UNLISTED, VideoPrivacy.PUBLIC, VideoPrivacy.PRIVATE ]
|
||||
})
|
||||
|
||||
expect(channelVideos).to.have.lengthOf(3)
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export * from './bitrate'
|
||||
export * from './privacy'
|
||||
|
|
9
shared/core-utils/videos/privacy.ts
Normal file
9
shared/core-utils/videos/privacy.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { VideoPrivacy } from '../../models/videos/video-privacy.enum'
|
||||
|
||||
function getAllPrivacies () {
|
||||
return [ VideoPrivacy.PUBLIC, VideoPrivacy.INTERNAL, VideoPrivacy.PRIVATE, VideoPrivacy.UNLISTED ]
|
||||
}
|
||||
|
||||
export {
|
||||
getAllPrivacies
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { VideoPrivacy } from '@shared/models'
|
||||
import { VideoInclude } from '../videos/video-include.enum'
|
||||
import { BooleanBothQuery } from './boolean-both-query.model'
|
||||
|
||||
|
@ -23,6 +24,8 @@ export interface VideosCommonQuery {
|
|||
|
||||
languageOneOf?: string[]
|
||||
|
||||
privacyOneOf?: VideoPrivacy[]
|
||||
|
||||
tagsOneOf?: string[]
|
||||
tagsAllOf?: string[]
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
export const enum VideoInclude {
|
||||
NONE = 0,
|
||||
NOT_PUBLISHED_STATE = 1 << 0,
|
||||
HIDDEN_PRIVACY = 1 << 1,
|
||||
BLACKLISTED = 1 << 2,
|
||||
BLOCKED_OWNER = 1 << 3,
|
||||
FILES = 1 << 4
|
||||
BLACKLISTED = 1 << 1,
|
||||
BLOCKED_OWNER = 1 << 2,
|
||||
FILES = 1 << 3
|
||||
}
|
||||
|
|
|
@ -369,6 +369,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
- $ref: '#/components/parameters/skipCount'
|
||||
|
@ -1305,6 +1306,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
- $ref: '#/components/parameters/skipCount'
|
||||
|
@ -1628,6 +1630,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
- $ref: '#/components/parameters/skipCount'
|
||||
|
@ -2867,6 +2870,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
- $ref: '#/components/parameters/skipCount'
|
||||
|
@ -3590,6 +3594,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
- $ref: '#/components/parameters/skipCount'
|
||||
|
@ -4095,6 +4100,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
responses:
|
||||
|
@ -4179,6 +4185,7 @@ paths:
|
|||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
- $ref: '#/components/parameters/hasHLSFiles'
|
||||
- $ref: '#/components/parameters/hasWebtorrentFiles'
|
||||
responses:
|
||||
|
@ -4834,6 +4841,13 @@ components:
|
|||
schema:
|
||||
type: boolean
|
||||
description: '**PeerTube >= 4.0** Display only videos that have WebTorrent files'
|
||||
privacyOneOf:
|
||||
name: privacyOneOf
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/VideoPrivacySet'
|
||||
description: '**PeerTube >= 4.0** Display only videos in this specific privacy/privacies'
|
||||
include:
|
||||
name: include
|
||||
in: query
|
||||
|
@ -4853,11 +4867,11 @@ components:
|
|||
|
||||
- `1` NOT_PUBLISHED_STATE
|
||||
|
||||
- `2` HIDDEN_PRIVACY
|
||||
- `2` BLACKLISTED
|
||||
|
||||
- `4` BLACKLISTED
|
||||
- `4` BLOCKED_OWNER
|
||||
|
||||
- `8` BLOCKED
|
||||
- `8` FILES
|
||||
subscriptionsUris:
|
||||
name: uris
|
||||
in: query
|
||||
|
|
Loading…
Reference in a new issue