Video channel API routes refractor
This commit is contained in:
parent
48dce1c90d
commit
6b738c7a31
18 changed files with 383 additions and 141 deletions
|
@ -18,7 +18,7 @@ import { AccountService } from '@app/shared/account/account.service'
|
|||
styleUrls: [ './account-about.component.scss' ]
|
||||
})
|
||||
export class AccountAboutComponent implements OnInit {
|
||||
private account: Account
|
||||
account: Account
|
||||
|
||||
constructor (
|
||||
protected route: ActivatedRoute,
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Account } from '@app/shared/account/account.model'
|
|||
styleUrls: [ './account.component.scss' ]
|
||||
})
|
||||
export class AccountComponent implements OnInit {
|
||||
private account: Account
|
||||
account: Account
|
||||
|
||||
constructor (
|
||||
private route: ActivatedRoute,
|
||||
|
|
|
@ -16,21 +16,6 @@ export class Account implements ServerAccount {
|
|||
updatedAt: Date
|
||||
avatar: Avatar
|
||||
|
||||
constructor (hash: ServerAccount) {
|
||||
this.id = hash.id
|
||||
this.uuid = hash.uuid
|
||||
this.url = hash.url
|
||||
this.name = hash.name
|
||||
this.displayName = hash.displayName
|
||||
this.description = hash.description
|
||||
this.host = hash.host
|
||||
this.followingCount = hash.followingCount
|
||||
this.followersCount = hash.followersCount
|
||||
this.createdAt = new Date(hash.createdAt.toString())
|
||||
this.updatedAt = new Date(hash.updatedAt.toString())
|
||||
this.avatar = hash.avatar
|
||||
}
|
||||
|
||||
static GET_ACCOUNT_AVATAR_URL (account: Account) {
|
||||
const absoluteAPIUrl = getAbsoluteAPIUrl()
|
||||
|
||||
|
@ -47,4 +32,19 @@ export class Account implements ServerAccount {
|
|||
|
||||
return accountName + '@' + host
|
||||
}
|
||||
|
||||
constructor (hash: ServerAccount) {
|
||||
this.id = hash.id
|
||||
this.uuid = hash.uuid
|
||||
this.url = hash.url
|
||||
this.name = hash.name
|
||||
this.displayName = hash.displayName
|
||||
this.description = hash.description
|
||||
this.host = hash.host
|
||||
this.followingCount = hash.followingCount
|
||||
this.followersCount = hash.followersCount
|
||||
this.createdAt = new Date(hash.createdAt.toString())
|
||||
this.updatedAt = new Date(hash.updatedAt.toString())
|
||||
this.avatar = hash.avatar
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,8 @@ async function addVideoChannelRetryWrapper (req: express.Request, res: express.R
|
|||
const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
|
||||
return res.json({
|
||||
videoChannel: {
|
||||
id: videoChannel.id
|
||||
id: videoChannel.id,
|
||||
uuid: videoChannel.Actor.uuid
|
||||
}
|
||||
}).end()
|
||||
}
|
||||
|
@ -233,7 +234,6 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon
|
|||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||
}
|
||||
|
||||
|
||||
async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
const account: AccountModel = res.locals.account
|
||||
|
||||
|
|
|
@ -185,7 +185,10 @@ async function createUserRetryWrapper (req: express.Request, res: express.Respon
|
|||
return res.json({
|
||||
user: {
|
||||
id: user.id,
|
||||
uuid: account.uuid
|
||||
account: {
|
||||
id: account.id,
|
||||
uuid: account.Actor.uuid
|
||||
}
|
||||
}
|
||||
}).end()
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { AccountModel } from '../models/account/account'
|
|||
import { UserModel } from '../models/account/user'
|
||||
import { buildActorInstance, getAccountActivityPubUrl, setAsyncActorKeys } from './activitypub'
|
||||
import { createVideoChannel } from './video-channel'
|
||||
import { VideoChannelModel } from '../models/video/video-channel'
|
||||
|
||||
async function createUserAccountAndChannel (userToCreate: UserModel, validateUser = true) {
|
||||
const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => {
|
||||
|
@ -28,7 +29,7 @@ async function createUserAccountAndChannel (userToCreate: UserModel, validateUse
|
|||
account.Actor = await setAsyncActorKeys(account.Actor)
|
||||
videoChannel.Actor = await setAsyncActorKeys(videoChannel.Actor)
|
||||
|
||||
return { user, account, videoChannel }
|
||||
return { user, account, videoChannel } as { user: UserModel, account: AccountModel, videoChannel: VideoChannelModel }
|
||||
}
|
||||
|
||||
async function createLocalAccountWithoutKeys (
|
||||
|
|
|
@ -11,6 +11,7 @@ import { logger } from '../../helpers/logger'
|
|||
import { UserModel } from '../../models/account/user'
|
||||
import { VideoChannelModel } from '../../models/video/video-channel'
|
||||
import { areValidationErrors } from './utils'
|
||||
import { AccountModel } from '../../models/account/account'
|
||||
|
||||
const listVideoAccountChannelsValidator = [
|
||||
param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
|
||||
|
@ -53,6 +54,7 @@ const videoChannelsUpdateValidator = [
|
|||
if (areValidationErrors(req, res)) return
|
||||
if (!await isAccountIdExist(req.params.accountId, res)) return
|
||||
if (!await isVideoChannelExist(req.params.id, res)) return
|
||||
if (!checkAccountOwnsVideoChannel(res.locals.account, res.locals.videoChannel, res)) return
|
||||
|
||||
// We need to make additional checks
|
||||
if (res.locals.videoChannel.Actor.isOwned() === false) {
|
||||
|
@ -82,6 +84,7 @@ const videoChannelsRemoveValidator = [
|
|||
if (!await isAccountIdExist(req.params.accountId, res)) return
|
||||
if (!await isVideoChannelExist(req.params.id, res)) return
|
||||
|
||||
if (!checkAccountOwnsVideoChannel(res.locals.account, res.locals.videoChannel, res)) return
|
||||
// Check if the user who did the request is able to delete the video
|
||||
if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return
|
||||
if (!await checkVideoChannelIsNotTheLastOne(res)) return
|
||||
|
@ -98,10 +101,13 @@ const videoChannelsGetValidator = [
|
|||
logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
// On some routes, accountId is optional (for example in the ActivityPub route)
|
||||
if (req.params.accountId && !await isAccountIdExist(req.params.accountId, res)) return
|
||||
if (!await isVideoChannelExist(req.params.id, res)) return
|
||||
|
||||
if (res.locals.account && !checkAccountOwnsVideoChannel(res.locals.account, res.locals.videoChannel, res)) return
|
||||
|
||||
return next()
|
||||
}
|
||||
]
|
||||
|
@ -154,3 +160,15 @@ async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
function checkAccountOwnsVideoChannel (account: AccountModel, videoChannel: VideoChannelModel, res: express.Response) {
|
||||
if (videoChannel.Account.id !== account.id) {
|
||||
res.status(400)
|
||||
.json({ error: 'This account does not own this video channel' })
|
||||
.end()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
|||
foreignKey: {
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'CASCADE'
|
||||
hooks: true
|
||||
})
|
||||
Account: AccountModel
|
||||
|
||||
|
@ -234,17 +234,26 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
|||
|
||||
toFormattedJSON (): VideoChannel {
|
||||
const actor = this.Actor.toFormattedJSON()
|
||||
const account = {
|
||||
const videoChannel = {
|
||||
id: this.id,
|
||||
displayName: this.name,
|
||||
description: this.description,
|
||||
support: this.support,
|
||||
isLocal: this.Actor.isOwned(),
|
||||
createdAt: this.createdAt,
|
||||
updatedAt: this.updatedAt
|
||||
updatedAt: this.updatedAt,
|
||||
ownerAccount: undefined,
|
||||
videos: undefined
|
||||
}
|
||||
|
||||
return Object.assign(actor, account)
|
||||
if (this.Account) {
|
||||
videoChannel.ownerAccount = {
|
||||
id: this.Account.id,
|
||||
uuid: this.Account.Actor.uuid
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign(actor, videoChannel)
|
||||
}
|
||||
|
||||
toActivityPubObject (): ActivityPubActor {
|
||||
|
|
|
@ -430,7 +430,7 @@ export class VideoModel extends Model<VideoModel> {
|
|||
foreignKey: {
|
||||
allowNull: true
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
hooks: true
|
||||
})
|
||||
VideoChannel: VideoChannelModel
|
||||
|
||||
|
@ -510,10 +510,12 @@ export class VideoModel extends Model<VideoModel> {
|
|||
return undefined
|
||||
}
|
||||
|
||||
@AfterDestroy
|
||||
@BeforeDestroy
|
||||
static async removeFilesAndSendDelete (instance: VideoModel) {
|
||||
const tasks: Promise<any>[] = []
|
||||
|
||||
logger.debug('Removing files of video %s.', instance.url)
|
||||
|
||||
tasks.push(instance.removeThumbnail())
|
||||
|
||||
if (instance.isOwned()) {
|
||||
|
@ -530,10 +532,13 @@ export class VideoModel extends Model<VideoModel> {
|
|||
})
|
||||
}
|
||||
|
||||
return Promise.all(tasks)
|
||||
// Do not wait video deletion because we could be in a transaction
|
||||
Promise.all(tasks)
|
||||
.catch(err => {
|
||||
logger.error('Some errors when removing files of video %s in after destroy hook.', instance.uuid, { err })
|
||||
})
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
static list () {
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
createUser,
|
||||
deleteVideoChannel,
|
||||
flushTests,
|
||||
getAccountVideoChannelsList,
|
||||
getAccountVideoChannelsList, getMyUserInformation,
|
||||
getVideoChannelsList,
|
||||
immutableAssign,
|
||||
killallServers,
|
||||
|
@ -21,6 +21,7 @@ import {
|
|||
} from '../../utils'
|
||||
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params'
|
||||
import { getAccountsList } from '../../utils/users/accounts'
|
||||
import { User } from '../../../../shared/models/users'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
|
@ -29,6 +30,8 @@ describe('Test videos API validator', function () {
|
|||
const accountPath = '/api/v1/accounts/'
|
||||
let server: ServerInfo
|
||||
let accessTokenUser: string
|
||||
let accountUUID: string
|
||||
let videoChannelUUID: string
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
|
@ -45,8 +48,18 @@ describe('Test videos API validator', function () {
|
|||
username: 'fake',
|
||||
password: 'fake_password'
|
||||
}
|
||||
await createUser(server.url, server.accessToken, user.username, user.password)
|
||||
accessTokenUser = await userLogin(server, user)
|
||||
|
||||
{
|
||||
await createUser(server.url, server.accessToken, user.username, user.password)
|
||||
accessTokenUser = await userLogin(server, user)
|
||||
}
|
||||
|
||||
{
|
||||
const res = await getMyUserInformation(server.url, server.accessToken)
|
||||
const user: User = res.body
|
||||
accountUUID = user.account.uuid
|
||||
videoChannelUUID = user.videoChannels[0].uuid
|
||||
}
|
||||
})
|
||||
|
||||
describe('When listing a video channels', function () {
|
||||
|
@ -74,18 +87,15 @@ describe('Test videos API validator', function () {
|
|||
})
|
||||
|
||||
describe('When adding a video channel', function () {
|
||||
let path: string
|
||||
|
||||
const baseCorrectParams = {
|
||||
name: 'hello',
|
||||
description: 'super description',
|
||||
support: 'super support text'
|
||||
}
|
||||
let path: string
|
||||
|
||||
before(async function () {
|
||||
const res = await getAccountsList(server.url)
|
||||
const accountId = res.body.data[0].id
|
||||
path = accountPath + accountId + '/video-channels'
|
||||
path = accountPath + accountUUID + '/video-channels'
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
|
@ -129,21 +139,14 @@ describe('Test videos API validator', function () {
|
|||
})
|
||||
|
||||
describe('When updating a video channel', function () {
|
||||
let path: string
|
||||
|
||||
const baseCorrectParams = {
|
||||
name: 'hello',
|
||||
description: 'super description'
|
||||
}
|
||||
let path: string
|
||||
|
||||
before(async function () {
|
||||
const res1 = await getVideoChannelsList(server.url, 0, 1)
|
||||
const videoChannelId = res1.body.data[0].id
|
||||
|
||||
const res2 = await getAccountsList(server.url)
|
||||
const accountId = res2.body.data[0].id
|
||||
|
||||
path = accountPath + accountId + '/video-channels/' + videoChannelId
|
||||
path = accountPath + accountUUID + '/video-channels/' + videoChannelUUID
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
|
@ -194,16 +197,9 @@ describe('Test videos API validator', function () {
|
|||
|
||||
describe('When getting a video channel', function () {
|
||||
let basePath: string
|
||||
let videoChannelId: number
|
||||
|
||||
before(async function () {
|
||||
const res1 = await getVideoChannelsList(server.url, 0, 1)
|
||||
videoChannelId = res1.body.data[0].id
|
||||
|
||||
const res2 = await getAccountsList(server.url)
|
||||
const accountId = res2.body.data[0].id
|
||||
|
||||
basePath = accountPath + accountId + '/video-channels'
|
||||
basePath = accountPath + accountUUID + '/video-channels'
|
||||
})
|
||||
|
||||
it('Should return the list of the video channels with nothing', async function () {
|
||||
|
@ -235,49 +231,38 @@ describe('Test videos API validator', function () {
|
|||
it('Should succeed with the correct parameters', async function () {
|
||||
await makeGetRequest({
|
||||
url: server.url,
|
||||
path: basePath + '/' + videoChannelId,
|
||||
path: basePath + '/' + videoChannelUUID,
|
||||
statusCodeExpected: 200
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('When deleting a video channel', function () {
|
||||
let videoChannelId: number
|
||||
let accountId: number
|
||||
|
||||
before(async function () {
|
||||
const res1 = await getVideoChannelsList(server.url, 0, 1)
|
||||
videoChannelId = res1.body.data[0].id
|
||||
|
||||
const res2 = await getAccountsList(server.url)
|
||||
accountId = res2.body.data[0].id
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
await deleteVideoChannel(server.url, 'coucou', accountId, videoChannelId, 401)
|
||||
await deleteVideoChannel(server.url, 'coucou', accountUUID, videoChannelUUID, 401)
|
||||
})
|
||||
|
||||
it('Should fail with another authenticated user', async function () {
|
||||
await deleteVideoChannel(server.url, accessTokenUser, accountId, videoChannelId, 403)
|
||||
await deleteVideoChannel(server.url, accessTokenUser, accountUUID, videoChannelUUID, 403)
|
||||
})
|
||||
|
||||
it('Should fail with an unknown account id', async function () {
|
||||
await deleteVideoChannel(server.url, server.accessToken, 454554,videoChannelId, 404)
|
||||
await deleteVideoChannel(server.url, server.accessToken, 454554,videoChannelUUID, 404)
|
||||
})
|
||||
|
||||
it('Should fail with an unknown video channel id', async function () {
|
||||
await deleteVideoChannel(server.url, server.accessToken, accountId,454554, 404)
|
||||
await deleteVideoChannel(server.url, server.accessToken, accountUUID,454554, 404)
|
||||
})
|
||||
|
||||
it('Should succeed with the correct parameters', async function () {
|
||||
await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId)
|
||||
await deleteVideoChannel(server.url, server.accessToken, accountUUID, videoChannelUUID)
|
||||
})
|
||||
|
||||
it('Should fail to delete the last user video channel', async function () {
|
||||
const res = await getVideoChannelsList(server.url, 0, 1)
|
||||
videoChannelId = res.body.data[0].id
|
||||
const lastVideoChannelUUID = res.body.data[0].uuid
|
||||
|
||||
await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId, 409)
|
||||
await deleteVideoChannel(server.url, server.accessToken, accountUUID, lastVideoChannelUUID, 409)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
makeGetRequest, makeUploadRequest, makePutBodyRequest, removeVideo, runServer, ServerInfo, setAccessTokensToServers, userLogin
|
||||
} from '../../utils'
|
||||
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params'
|
||||
import { getAccountsList } from '../../utils/users/accounts'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
|
@ -17,7 +18,9 @@ describe('Test videos API validator', function () {
|
|||
const path = '/api/v1/videos/'
|
||||
let server: ServerInfo
|
||||
let userAccessToken = ''
|
||||
let accountUUID: string
|
||||
let channelId: number
|
||||
let channelUUID: string
|
||||
let videoId
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
@ -36,8 +39,12 @@ describe('Test videos API validator', function () {
|
|||
await createUser(server.url, server.accessToken, username, password)
|
||||
userAccessToken = await userLogin(server, { username, password })
|
||||
|
||||
const res = await getMyUserInformation(server.url, server.accessToken)
|
||||
channelId = res.body.videoChannels[0].id
|
||||
{
|
||||
const res = await getMyUserInformation(server.url, server.accessToken)
|
||||
channelId = res.body.videoChannels[ 0 ].id
|
||||
channelUUID = res.body.videoChannels[ 0 ].uuid
|
||||
accountUUID = res.body.account.uuid
|
||||
}
|
||||
})
|
||||
|
||||
describe('When listing a video', function () {
|
||||
|
@ -52,6 +59,10 @@ describe('Test videos API validator', function () {
|
|||
it('Should fail with an incorrect sort', async function () {
|
||||
await checkBadSortPagination(server.url, path)
|
||||
})
|
||||
|
||||
it('Should success with the correct parameters', async function () {
|
||||
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When searching a video', function () {
|
||||
|
@ -75,6 +86,10 @@ describe('Test videos API validator', function () {
|
|||
it('Should fail with an incorrect sort', async function () {
|
||||
await checkBadSortPagination(server.url, join(path, 'search', 'test'))
|
||||
})
|
||||
|
||||
it('Should success with the correct parameters', async function () {
|
||||
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When listing my videos', function () {
|
||||
|
@ -91,6 +106,58 @@ describe('Test videos API validator', function () {
|
|||
it('Should fail with an incorrect sort', async function () {
|
||||
await checkBadSortPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should success with the correct parameters', async function () {
|
||||
await makeGetRequest({ url: server.url, token: server.accessToken, path, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When listing account videos', function () {
|
||||
let path: string
|
||||
|
||||
before(async function () {
|
||||
path = '/api/v1/accounts/' + accountUUID + '/videos'
|
||||
})
|
||||
|
||||
it('Should fail with a bad start pagination', async function () {
|
||||
await checkBadStartPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should fail with a bad count pagination', async function () {
|
||||
await checkBadCountPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should fail with an incorrect sort', async function () {
|
||||
await checkBadSortPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should success with the correct parameters', async function () {
|
||||
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When listing video channel videos', function () {
|
||||
let path: string
|
||||
|
||||
before(async function () {
|
||||
path = '/api/v1/accounts/' + accountUUID + '/video-channels/' + channelUUID + '/videos'
|
||||
})
|
||||
|
||||
it('Should fail with a bad start pagination', async function () {
|
||||
await checkBadStartPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should fail with a bad count pagination', async function () {
|
||||
await checkBadCountPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should fail with an incorrect sort', async function () {
|
||||
await checkBadSortPagination(server.url, path, server.accessToken)
|
||||
})
|
||||
|
||||
it('Should success with the correct parameters', async function () {
|
||||
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When adding a video', function () {
|
||||
|
@ -112,7 +179,7 @@ describe('Test videos API validator', function () {
|
|||
support: 'my super support text',
|
||||
tags: [ 'tag1', 'tag2' ],
|
||||
privacy: VideoPrivacy.PUBLIC,
|
||||
channelId
|
||||
channelId: channelId
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -4,22 +4,33 @@ import * as chai from 'chai'
|
|||
import 'mocha'
|
||||
import { Account } from '../../../../shared/models/actors'
|
||||
import {
|
||||
checkVideoFilesWereRemoved, createUser, doubleFollow, flushAndRunMultipleServers, removeUser, updateMyUser, userLogin,
|
||||
checkVideoFilesWereRemoved,
|
||||
createUser,
|
||||
doubleFollow,
|
||||
flushAndRunMultipleServers,
|
||||
getAccountVideos,
|
||||
getVideoChannelsList,
|
||||
removeUser,
|
||||
updateMyUser,
|
||||
userLogin,
|
||||
wait
|
||||
} from '../../utils'
|
||||
import { flushTests, getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../utils/index'
|
||||
import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../utils/users/accounts'
|
||||
import { setAccessTokensToServers } from '../../utils/users/login'
|
||||
import { User } from '../../../../shared/models/users'
|
||||
import { VideoChannel } from '../../../../shared/models/videos'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('Test users with multiple servers', function () {
|
||||
let servers: ServerInfo[] = []
|
||||
let user
|
||||
let userUUID
|
||||
let userId
|
||||
let videoUUID
|
||||
let userAccessToken
|
||||
let user: User
|
||||
let userAccountUUID: string
|
||||
let userVideoChannelUUID: string
|
||||
let userId: number
|
||||
let videoUUID: string
|
||||
let userAccessToken: string
|
||||
|
||||
before(async function () {
|
||||
this.timeout(120000)
|
||||
|
@ -39,17 +50,28 @@ describe('Test users with multiple servers', function () {
|
|||
// The root user of server 1 is propagated to servers 2 and 3
|
||||
await uploadVideo(servers[0].url, servers[0].accessToken, {})
|
||||
|
||||
const user = {
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
}
|
||||
const resUser = await createUser(servers[0].url, servers[0].accessToken, user.username, user.password)
|
||||
userUUID = resUser.body.user.uuid
|
||||
userId = resUser.body.user.id
|
||||
userAccessToken = await userLogin(servers[0], user)
|
||||
{
|
||||
const user = {
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
}
|
||||
const res = await createUser(servers[ 0 ].url, servers[ 0 ].accessToken, user.username, user.password)
|
||||
userAccountUUID = res.body.user.account.uuid
|
||||
userId = res.body.user.id
|
||||
|
||||
const resVideo = await uploadVideo(servers[0].url, userAccessToken, {})
|
||||
videoUUID = resVideo.body.uuid
|
||||
userAccessToken = await userLogin(servers[ 0 ], user)
|
||||
}
|
||||
|
||||
{
|
||||
const res = await getMyUserInformation(servers[ 0 ].url, servers[ 0 ].accessToken)
|
||||
const user: User = res.body
|
||||
userVideoChannelUUID = user.videoChannels[0].uuid
|
||||
}
|
||||
|
||||
{
|
||||
const resVideo = await uploadVideo(servers[ 0 ].url, userAccessToken, {})
|
||||
videoUUID = resVideo.body.video.uuid
|
||||
}
|
||||
|
||||
await wait(5000)
|
||||
})
|
||||
|
@ -106,14 +128,31 @@ describe('Test users with multiple servers', function () {
|
|||
}
|
||||
})
|
||||
|
||||
it('Should list account videos', async function () {
|
||||
for (const server of servers) {
|
||||
const res = await getAccountVideos(server.url, server.accessToken, userAccountUUID, 0, 5)
|
||||
|
||||
expect(res.body.total).to.equal(1)
|
||||
expect(res.body.data).to.be.an('array')
|
||||
expect(res.body.data).to.have.lengthOf(1)
|
||||
expect(res.body.data[0].uuid).to.equal(videoUUID)
|
||||
}
|
||||
})
|
||||
|
||||
it('Should remove the user', async function () {
|
||||
this.timeout(10000)
|
||||
|
||||
for (const server of servers) {
|
||||
const resAccounts = await getAccountsList(server.url, '-createdAt')
|
||||
|
||||
const userServer1List = resAccounts.body.data.find(a => a.name === 'user1' && a.host === 'localhost:9001') as Account
|
||||
expect(userServer1List).not.to.be.undefined
|
||||
const accountDeleted = resAccounts.body.data.find(a => a.name === 'user1' && a.host === 'localhost:9001') as Account
|
||||
expect(accountDeleted).not.to.be.undefined
|
||||
|
||||
const resVideoChannels = await getVideoChannelsList(server.url, 0, 10)
|
||||
const videoChannelDeleted = resVideoChannels.body.data.find(a => {
|
||||
return a.displayName === 'Default user1 channel' && a.host === 'localhost:9001'
|
||||
}) as VideoChannel
|
||||
expect(videoChannelDeleted).not.to.be.undefined
|
||||
}
|
||||
|
||||
await removeUser(servers[0].url, userId, servers[0].accessToken)
|
||||
|
@ -123,14 +162,21 @@ describe('Test users with multiple servers', function () {
|
|||
for (const server of servers) {
|
||||
const resAccounts = await getAccountsList(server.url, '-createdAt')
|
||||
|
||||
const userServer1List = resAccounts.body.data.find(a => a.name === 'user1' && a.host === 'localhost:9001') as Account
|
||||
expect(userServer1List).to.be.undefined
|
||||
const accountDeleted = resAccounts.body.data.find(a => a.name === 'user1' && a.host === 'localhost:9001') as Account
|
||||
expect(accountDeleted).to.be.undefined
|
||||
|
||||
const resVideoChannels = await getVideoChannelsList(server.url, 0, 10)
|
||||
const videoChannelDeleted = resVideoChannels.body.data.find(a => {
|
||||
return a.name === 'Default user1 channel' && a.host === 'localhost:9001'
|
||||
}) as VideoChannel
|
||||
expect(videoChannelDeleted).to.be.undefined
|
||||
}
|
||||
})
|
||||
|
||||
it('Should not have actor files', async () => {
|
||||
for (const server of servers) {
|
||||
await checkActorFilesWereRemoved(userUUID, server.serverNumber)
|
||||
await checkActorFilesWereRemoved(userAccountUUID, server.serverNumber)
|
||||
await checkActorFilesWereRemoved(userVideoChannelUUID, server.serverNumber)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import * as chai from 'chai'
|
||||
import 'mocha'
|
||||
import { User } from '../../../../shared/index'
|
||||
import { doubleFollow, flushAndRunMultipleServers, uploadVideo, wait } from '../../utils'
|
||||
import { doubleFollow, flushAndRunMultipleServers, getVideoChannelVideos, uploadVideo, wait } from '../../utils'
|
||||
import {
|
||||
addVideoChannel,
|
||||
deleteVideoChannel,
|
||||
|
@ -24,8 +24,9 @@ const expect = chai.expect
|
|||
describe('Test video channels', function () {
|
||||
let servers: ServerInfo[]
|
||||
let userInfo: User
|
||||
let accountId: number
|
||||
let accountUUID: string
|
||||
let videoChannelId: number
|
||||
let videoChannelUUID: string
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000)
|
||||
|
@ -38,8 +39,9 @@ describe('Test video channels', function () {
|
|||
await doubleFollow(servers[0], servers[1])
|
||||
|
||||
{
|
||||
const res = await getAccountsList(servers[0].url)
|
||||
accountId = res.body.data[0].id
|
||||
const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
|
||||
const user: User = res.body
|
||||
accountUUID = user.account.uuid
|
||||
}
|
||||
|
||||
await wait(5000)
|
||||
|
@ -61,11 +63,12 @@ describe('Test video channels', function () {
|
|||
description: 'super video channel description',
|
||||
support: 'super video channel support text'
|
||||
}
|
||||
const res = await addVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannel)
|
||||
const res = await addVideoChannel(servers[0].url, servers[0].accessToken, accountUUID, videoChannel)
|
||||
videoChannelId = res.body.videoChannel.id
|
||||
videoChannelUUID = res.body.videoChannel.uuid
|
||||
|
||||
// The channel is 1 is propagated to servers 2
|
||||
await uploadVideo(servers[0].url, servers[0].accessToken, { channelId: videoChannelId })
|
||||
await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'my video name', channelId: videoChannelId })
|
||||
|
||||
await wait(3000)
|
||||
})
|
||||
|
@ -127,7 +130,7 @@ describe('Test video channels', function () {
|
|||
support: 'video channel support text updated'
|
||||
}
|
||||
|
||||
await updateVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId, videoChannelAttributes)
|
||||
await updateVideoChannel(servers[0].url, servers[0].accessToken, accountUUID, videoChannelId, videoChannelAttributes)
|
||||
|
||||
await wait(3000)
|
||||
})
|
||||
|
@ -146,7 +149,7 @@ describe('Test video channels', function () {
|
|||
})
|
||||
|
||||
it('Should get video channel', async function () {
|
||||
const res = await getVideoChannel(servers[0].url, accountId, videoChannelId)
|
||||
const res = await getVideoChannel(servers[0].url, accountUUID, videoChannelId)
|
||||
|
||||
const videoChannel = res.body
|
||||
expect(videoChannel.displayName).to.equal('video channel updated')
|
||||
|
@ -154,8 +157,20 @@ describe('Test video channels', function () {
|
|||
expect(videoChannel.support).to.equal('video channel support text updated')
|
||||
})
|
||||
|
||||
it('Should list the video channel videos', async function () {
|
||||
this.timeout(10000)
|
||||
|
||||
for (const server of servers) {
|
||||
const res = await getVideoChannelVideos(server.url, server.accessToken, accountUUID, videoChannelUUID, 0, 5)
|
||||
expect(res.body.total).to.equal(1)
|
||||
expect(res.body.data).to.be.an('array')
|
||||
expect(res.body.data).to.have.lengthOf(1)
|
||||
expect(res.body.data[0].name).to.equal('my video name')
|
||||
}
|
||||
})
|
||||
|
||||
it('Should delete video channel', async function () {
|
||||
await deleteVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId)
|
||||
await deleteVideoChannel(servers[0].url, servers[0].accessToken, accountUUID, videoChannelId)
|
||||
})
|
||||
|
||||
it('Should have video channel deleted', async function () {
|
||||
|
|
|
@ -7,8 +7,9 @@ import { userLogin } from '../../utils/users/login'
|
|||
import { createUser } from '../../utils/users/users'
|
||||
import { getMyVideos } from '../../utils/videos/videos'
|
||||
import {
|
||||
getAccountVideos,
|
||||
getConfig, getCustomConfig,
|
||||
getMyUserInformation,
|
||||
getMyUserInformation, getVideoChannelVideos,
|
||||
getVideosListWithToken,
|
||||
runServer,
|
||||
searchVideo,
|
||||
|
@ -17,6 +18,7 @@ import {
|
|||
} from '../../utils'
|
||||
import { ServerConfig } from '../../../../shared/models'
|
||||
import { CustomConfig } from '../../../../shared/models/server/custom-config.model'
|
||||
import { User } from '../../../../shared/models/users'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
|
@ -25,6 +27,31 @@ describe('Test video NSFW policy', function () {
|
|||
let userAccessToken: string
|
||||
let customConfig: CustomConfig
|
||||
|
||||
function getVideosFunctions (token?: string) {
|
||||
return getMyUserInformation(server.url, server.accessToken)
|
||||
.then(res => {
|
||||
const user: User = res.body
|
||||
const videoChannelUUID = user.videoChannels[0].uuid
|
||||
const accountUUID = user.account.uuid
|
||||
|
||||
if (token) {
|
||||
return Promise.all([
|
||||
getVideosListWithToken(server.url, token),
|
||||
searchVideoWithToken(server.url, 'n', token),
|
||||
getAccountVideos(server.url, token, accountUUID, 0, 5),
|
||||
getVideoChannelVideos(server.url, token, accountUUID, videoChannelUUID, 0, 5)
|
||||
])
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
getVideosList(server.url),
|
||||
searchVideo(server.url, 'n'),
|
||||
getAccountVideos(server.url, undefined, accountUUID, 0, 5),
|
||||
getVideoChannelVideos(server.url, undefined, accountUUID, videoChannelUUID, 0, 5)
|
||||
])
|
||||
})
|
||||
}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(50000)
|
||||
|
||||
|
@ -56,7 +83,7 @@ describe('Test video NSFW policy', function () {
|
|||
const serverConfig: ServerConfig = resConfig.body
|
||||
expect(serverConfig.instance.defaultNSFWPolicy).to.equal('display')
|
||||
|
||||
for (const res of [ await getVideosList(server.url), await searchVideo(server.url, 'n') ]) {
|
||||
for (const res of await getVideosFunctions()) {
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos = res.body.data
|
||||
|
@ -74,7 +101,7 @@ describe('Test video NSFW policy', function () {
|
|||
const serverConfig: ServerConfig = resConfig.body
|
||||
expect(serverConfig.instance.defaultNSFWPolicy).to.equal('do_not_list')
|
||||
|
||||
for (const res of [ await getVideosList(server.url), await searchVideo(server.url, 'n') ]) {
|
||||
for (const res of await getVideosFunctions()) {
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const videos = res.body.data
|
||||
|
@ -91,7 +118,7 @@ describe('Test video NSFW policy', function () {
|
|||
const serverConfig: ServerConfig = resConfig.body
|
||||
expect(serverConfig.instance.defaultNSFWPolicy).to.equal('blur')
|
||||
|
||||
for (const res of [ await getVideosList(server.url), await searchVideo(server.url, 'n') ]) {
|
||||
for (const res of await getVideosFunctions()) {
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos = res.body.data
|
||||
|
@ -118,12 +145,7 @@ describe('Test video NSFW policy', function () {
|
|||
})
|
||||
|
||||
it('Should display NSFW videos with blur user NSFW policy', async function () {
|
||||
const results = [
|
||||
await getVideosListWithToken(server.url, userAccessToken),
|
||||
await searchVideoWithToken(server.url, 'n', userAccessToken)
|
||||
]
|
||||
|
||||
for (const res of results) {
|
||||
for (const res of await getVideosFunctions(userAccessToken)) {
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos = res.body.data
|
||||
|
@ -140,12 +162,7 @@ describe('Test video NSFW policy', function () {
|
|||
nsfwPolicy: 'display'
|
||||
})
|
||||
|
||||
const results = [
|
||||
await getVideosListWithToken(server.url, server.accessToken),
|
||||
await searchVideoWithToken(server.url, 'n', server.accessToken)
|
||||
]
|
||||
|
||||
for (const res of results) {
|
||||
for (const res of await getVideosFunctions(server.accessToken)) {
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos = res.body.data
|
||||
|
@ -162,11 +179,7 @@ describe('Test video NSFW policy', function () {
|
|||
nsfwPolicy: 'do_not_list'
|
||||
})
|
||||
|
||||
const results = [
|
||||
await getVideosListWithToken(server.url, server.accessToken),
|
||||
await searchVideoWithToken(server.url, 'n', server.accessToken)
|
||||
]
|
||||
for (const res of results) {
|
||||
for (const res of await getVideosFunctions(server.accessToken)) {
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const videos = res.body.data
|
||||
|
|
|
@ -34,7 +34,7 @@ function getAccountVideoChannelsList (url: string, accountId: number | string, s
|
|||
function addVideoChannel (
|
||||
url: string,
|
||||
token: string,
|
||||
accountId: number,
|
||||
accountId: number | string,
|
||||
videoChannelAttributesArg: VideoChannelAttributes,
|
||||
expectedStatus = 200
|
||||
) {
|
||||
|
@ -59,8 +59,8 @@ function addVideoChannel (
|
|||
function updateVideoChannel (
|
||||
url: string,
|
||||
token: string,
|
||||
accountId: number,
|
||||
channelId: number,
|
||||
accountId: number | string,
|
||||
channelId: number | string,
|
||||
attributes: VideoChannelAttributes,
|
||||
expectedStatus = 204
|
||||
) {
|
||||
|
@ -79,7 +79,7 @@ function updateVideoChannel (
|
|||
.expect(expectedStatus)
|
||||
}
|
||||
|
||||
function deleteVideoChannel (url: string, token: string, accountId: number, channelId: number, expectedStatus = 204) {
|
||||
function deleteVideoChannel (url: string, token: string, accountId: number | string, channelId: number | string, expectedStatus = 204) {
|
||||
const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
|
||||
|
||||
return request(url)
|
||||
|
@ -89,7 +89,7 @@ function deleteVideoChannel (url: string, token: string, accountId: number, chan
|
|||
.expect(expectedStatus)
|
||||
}
|
||||
|
||||
function getVideoChannel (url: string, accountId: number, channelId: number) {
|
||||
function getVideoChannel (url: string, accountId: number | string, channelId: number | string) {
|
||||
const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
|
||||
|
||||
return request(url)
|
||||
|
|
|
@ -167,6 +167,46 @@ function getMyVideos (url: string, accessToken: string, start: number, count: nu
|
|||
.expect('Content-Type', /json/)
|
||||
}
|
||||
|
||||
function getAccountVideos (url: string, accessToken: string, accountId: number | string, start: number, count: number, sort?: string) {
|
||||
const path = '/api/v1/accounts/' + accountId + '/videos'
|
||||
|
||||
return makeGetRequest({
|
||||
url,
|
||||
path,
|
||||
query: {
|
||||
start,
|
||||
count,
|
||||
sort
|
||||
},
|
||||
token: accessToken,
|
||||
statusCodeExpected: 200
|
||||
})
|
||||
}
|
||||
|
||||
function getVideoChannelVideos (
|
||||
url: string,
|
||||
accessToken: string,
|
||||
accountId: number | string,
|
||||
videoChannelId: number | string,
|
||||
start: number,
|
||||
count: number,
|
||||
sort?: string
|
||||
) {
|
||||
const path = '/api/v1/accounts/' + accountId + '/video-channels/' + videoChannelId + '/videos'
|
||||
|
||||
return makeGetRequest({
|
||||
url,
|
||||
path,
|
||||
query: {
|
||||
start,
|
||||
count,
|
||||
sort
|
||||
},
|
||||
token: accessToken,
|
||||
statusCodeExpected: 200
|
||||
})
|
||||
}
|
||||
|
||||
function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
|
||||
const path = '/api/v1/videos'
|
||||
|
||||
|
@ -514,6 +554,8 @@ export {
|
|||
getVideoPrivacies,
|
||||
getVideoLanguages,
|
||||
getMyVideos,
|
||||
getAccountVideos,
|
||||
getVideoChannelVideos,
|
||||
searchVideoWithToken,
|
||||
getVideo,
|
||||
getVideoWithToken,
|
||||
|
|
|
@ -6,9 +6,8 @@ export interface VideoChannel extends Actor {
|
|||
description: string
|
||||
support: string
|
||||
isLocal: boolean
|
||||
owner?: {
|
||||
name: string
|
||||
ownerAccount?: {
|
||||
id: number
|
||||
uuid: string
|
||||
}
|
||||
videos?: Video[]
|
||||
}
|
||||
|
|
|
@ -50,6 +50,25 @@ paths:
|
|||
description: successful operation
|
||||
schema:
|
||||
$ref: '#/definitions/Account'
|
||||
'/accounts/{id}/videos':
|
||||
get:
|
||||
tags:
|
||||
- Accounts
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: 'The id of the account'
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
$ref: '#/definitions/Video'
|
||||
/accounts:
|
||||
get:
|
||||
tags:
|
||||
|
@ -1115,6 +1134,30 @@ paths:
|
|||
responses:
|
||||
'204':
|
||||
description: successful operation
|
||||
"/account/{accountId}/video-channels/{id}/videos":
|
||||
get:
|
||||
tags:
|
||||
- VideoChannel
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- name: accountId
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: 'The account id '
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: 'The video channel id '
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
$ref: '#/definitions/Video'
|
||||
"/videos/{videoId}/comment-threads":
|
||||
get:
|
||||
tags:
|
||||
|
@ -1387,17 +1430,13 @@ definitions:
|
|||
type: string
|
||||
isLocal:
|
||||
type: boolean
|
||||
owner:
|
||||
ownerAccount:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
id:
|
||||
type: number
|
||||
uuid:
|
||||
type: string
|
||||
videos:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Video"
|
||||
VideoComment:
|
||||
properties:
|
||||
id:
|
||||
|
|
Loading…
Reference in a new issue