Skip to content

Commit

Permalink
Change REST API for importing videos into channel (Chocobozzz#754)
Browse files Browse the repository at this point in the history
  • Loading branch information
fflorent committed Aug 8, 2022
1 parent 4f023e6 commit 9dc5088
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 212 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<my-select-channel
required
[items]="userVideoChannels"
[(ngModel)]="selectedVideoChannel"
[(ngModel)]="selectedChannelId"
formControlName="videoChannel">
</my-select-channel>
<div *ngIf="formErrors['videoChannel']" class="form-error">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { AuthService, Notifier } from '@app/core'
import { listUserChannelsForSelect } from '@app/helpers'
import { VIDEO_CHANNEL_EXTERNAL_URL_VALIDATOR } from '@app/shared/form-validators/video-channel-validators'
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { VideoChannelSyncService } from '@app/shared/shared-main'
import { VideoChannel, VideoChannelSyncCreate } from '@shared/models/videos'
import { VideoChannelService, VideoChannelSyncService } from '@app/shared/shared-main'
import { VideoChannelSyncCreate } from '@shared/models/videos'
import { mergeMap } from 'rxjs'
import { SelectChannelItem } from 'src/types'

Expand All @@ -16,7 +16,7 @@ import { SelectChannelItem } from 'src/types'
})
export class VideoChannelSyncEditComponent extends FormReactive implements OnInit {
error: string
selectedVideoChannel: VideoChannel
selectedChannelId: number
userVideoChannels: SelectChannelItem[]
existingVideosStrategy: string

Expand All @@ -25,7 +25,8 @@ export class VideoChannelSyncEditComponent extends FormReactive implements OnIni
private authService: AuthService,
private router: Router,
private notifier: Notifier,
private videoChannelSyncService: VideoChannelSyncService
private videoChannelSyncService: VideoChannelSyncService,
private videoChannelService: VideoChannelService
) {
super()
}
Expand Down Expand Up @@ -57,8 +58,9 @@ export class VideoChannelSyncEditComponent extends FormReactive implements OnIni
.pipe(mergeMap((res: {videoChannelSync: {id: number}}) => {
this.authService.refreshUserInformation()

const selectedChannel = this.authService.getUser().videoChannels.find(video => video.id === this.selectedChannelId)
return importExistingVideos
? this.videoChannelSyncService.syncChannel(res.videoChannelSync.id)
? this.videoChannelService.importVideos(selectedChannel.name, body.externalChannelUrl)
: Promise.resolve(null)
}))
.subscribe({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,4 @@ export class VideoChannelSyncService {
return this.authHttp.delete(url)
.pipe(catchError(err => this.restExtractor.handleError(err)))
}

syncChannel (syncId: number) {
const url = `${VideoChannelSyncService.BASE_VIDEO_CHANNEL_URL}/${syncId}/sync`
return this.authHttp.post(url, {})
.pipe(catchError(err => this.restExtractor.handleError(err)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,10 @@ export class VideoChannelService {
return this.authHttp.delete(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost)
.pipe(catchError(err => this.restExtractor.handleError(err)))
}

importVideos (videoChannelName: string, externalChannelUrl: string) {
const path = VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannelName + '/import-videos'
return this.authHttp.post(path, { externalChannelUrl })
.pipe(catchError(err => this.restExtractor.handleError(err)))
}
}
28 changes: 0 additions & 28 deletions server/controllers/api/video-channel-sync.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelSyncAuditView } from '@server/helpers/audit-logger'
import { logger } from '@server/helpers/logger'
import { sequelizeTypescript } from '@server/initializers/database'
import { JobQueue } from '@server/lib/job-queue'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
authenticate,
ensureCanManageChannel as ensureCanManageSyncedChannel,
ensureCanUpload,
ensureSyncExists,
ensureSyncIsEnabled,
videoChannelSyncValidator
Expand All @@ -27,15 +25,6 @@ videoChannelSyncRouter.post('/',
asyncRetryTransactionMiddleware(createVideoChannelSync)
)

videoChannelSyncRouter.post('/:id/sync',
authenticate,
ensureSyncIsEnabled,
asyncMiddleware(ensureSyncExists),
ensureCanManageSyncedChannel,
asyncMiddleware(ensureCanUpload),
syncChannel
)

videoChannelSyncRouter.delete('/:id',
authenticate,
asyncMiddleware(ensureSyncExists),
Expand Down Expand Up @@ -84,20 +73,3 @@ async function removeVideoChannelSync (req: express.Request, res: express.Respon
)
return res.type('json').status(HttpStatusCode.NO_CONTENT_204).end()
}

function syncChannel (req: express.Request, res: express.Response) {
const { externalChannelUrl, videoChannelId } = res.locals.videoChannelSync
JobQueue.Instance.createJob({
type: 'video-channel-import',
payload: {
externalChannelUrl,
videoChannelId
}
})
logger.info(
'Video import job for channel "%s" with external channel "%s" created.',
res.locals.videoChannel.name,
externalChannelUrl
)
return res.type('json').status(HttpStatusCode.NO_CONTENT_204).end()
}
30 changes: 30 additions & 0 deletions server/controllers/api/video-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import {
videoPlaylistsSortValidator
} from '../../middlewares'
import {
ensureChannelOwnerCanUpload,
ensureIsLocalChannel,
videoChannelImportVideosValidator,
videoChannelsFollowersSortValidator,
videoChannelsListValidator,
videoChannelsNameWithHostValidator,
Expand Down Expand Up @@ -161,6 +163,16 @@ videoChannelRouter.get('/:nameWithHost/followers',
asyncMiddleware(listVideoChannelFollowers)
)

videoChannelRouter.post('/:nameWithHost/import-videos',
authenticate,
asyncMiddleware(videoChannelsNameWithHostValidator),
videoChannelImportVideosValidator,
ensureIsLocalChannel,
ensureCanManageChannel,
asyncMiddleware(ensureChannelOwnerCanUpload),
importVideosOnChannel
)

// ---------------------------------------------------------------------------

export {
Expand Down Expand Up @@ -404,3 +416,21 @@ async function listVideoChannelFollowers (req: express.Request, res: express.Res

return res.json(getFormattedObjects(resultList.data, resultList.total))
}

function importVideosOnChannel (req: express.Request, res: express.Response) {
const { id: videoChannelId } = res.locals.videoChannel
const { externalChannelUrl } = req.body
JobQueue.Instance.createJob({
type: 'video-channel-import',
payload: {
externalChannelUrl,
videoChannelId
}
})
logger.info(
'Video import job for channel "%s" with url "%s" created.',
res.locals.videoChannel.name,
externalChannelUrl
)
return res.type('json').status(HttpStatusCode.NO_CONTENT_204).end()
}
17 changes: 3 additions & 14 deletions server/middlewares/validators/videos/video-channel-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as express from 'express'
import { isUrlValid } from "@server/helpers/custom-validators/activitypub/misc"
import { logger } from "@server/helpers/logger"
import { body, param } from "express-validator"
import { areValidationErrors, checkUserQuota, doesVideoChannelIdExist } from "../shared"
import { areValidationErrors, doesVideoChannelIdExist } from "../shared"
import { HttpStatusCode, VideoChannelSyncCreate } from '@shared/models'
import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync'
import { CONFIG } from '@server/initializers/config'
Expand All @@ -11,7 +11,7 @@ export const ensureSyncIsEnabled = (req: express.Request, res: express.Response,
if (!CONFIG.IMPORT.SYNCHRONIZATION.ENABLED) {
return res.fail({
status: HttpStatusCode.FORBIDDEN_403,
message: 'Synchronization is impossible as video upload via HTTP is not enabled on the server'
message: 'Synchronization is impossible as video channel synchronization is not enabled on the server'
})
}
return next()
Expand All @@ -22,7 +22,7 @@ export const videoChannelSyncValidator = [
body('videoChannelId').isInt().withMessage('Should have a valid video channel id'),

async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body })
logger.debug('Checking videoChannelSync parameters', { parameters: req.body })

if (areValidationErrors(req, res)) return

Expand Down Expand Up @@ -52,14 +52,3 @@ export const ensureSyncExists = [
return next()
}
]

export const ensureCanUpload = [
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
const sync = res.locals.videoChannelSync
const user = {
id: sync.VideoChannel.Account.userId
}
if (!await checkUserQuota(user, 1, res)) return
next()
}
]
54 changes: 36 additions & 18 deletions server/middlewares/validators/videos/video-channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {
import { logger } from '../../../helpers/logger'
import { ActorModel } from '../../../models/actor/actor'
import { VideoChannelModel } from '../../../models/video/video-channel'
import { areValidationErrors, doesVideoChannelNameWithHostExist } from '../shared'
import { areValidationErrors, checkUserQuota, doesVideoChannelNameWithHostExist } from '../shared'
import { isUrlValid } from '@server/helpers/custom-validators/activitypub/misc'

const videoChannelsAddValidator = [
export const videoChannelsAddValidator = [
body('name').custom(isVideoChannelUsernameValid).withMessage('Should have a valid channel name'),
body('displayName').custom(isVideoChannelDisplayNameValid).withMessage('Should have a valid display name'),
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
Expand Down Expand Up @@ -45,7 +46,7 @@ const videoChannelsAddValidator = [
}
]

const videoChannelsUpdateValidator = [
export const videoChannelsUpdateValidator = [
param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
body('displayName')
.optional()
Expand All @@ -69,7 +70,7 @@ const videoChannelsUpdateValidator = [
}
]

const videoChannelsRemoveValidator = [
export const videoChannelsRemoveValidator = [
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })

Expand All @@ -79,7 +80,7 @@ const videoChannelsRemoveValidator = [
}
]

const videoChannelsNameWithHostValidator = [
export const videoChannelsNameWithHostValidator = [
param('nameWithHost').exists().withMessage('Should have an video channel name with host'),

async (req: express.Request, res: express.Response, next: express.NextFunction) => {
Expand All @@ -93,7 +94,7 @@ const videoChannelsNameWithHostValidator = [
}
]

const ensureIsLocalChannel = [
export const ensureIsLocalChannel = [
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (res.locals.videoChannel.Actor.isOwned() === false) {
return res.fail({
Expand All @@ -106,7 +107,18 @@ const ensureIsLocalChannel = [
}
]

const videoChannelStatsValidator = [
export const ensureChannelOwnerCanUpload = [
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
const channel = res.locals.videoChannel
const user = {
id: channel.Account.userId
}
if (!await checkUserQuota(user, 1, res)) return
next()
}
]

export const videoChannelStatsValidator = [
query('withStats')
.optional()
.customSanitizer(toBooleanOrNull)
Expand All @@ -118,7 +130,7 @@ const videoChannelStatsValidator = [
}
]

const videoChannelsListValidator = [
export const videoChannelsListValidator = [
query('search').optional().not().isEmpty().withMessage('Should have a valid search'),

(req: express.Request, res: express.Response, next: express.NextFunction) => {
Expand All @@ -130,17 +142,23 @@ const videoChannelsListValidator = [
}
]

// ---------------------------------------------------------------------------
export const videoChannelImportVideosValidator = [
body('externalChannelUrl').custom(isUrlValid).withMessage('Should have a valid channel url'),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoChannelImport parameters', { parameters: req.body })

export {
videoChannelsAddValidator,
videoChannelsUpdateValidator,
videoChannelsRemoveValidator,
videoChannelsNameWithHostValidator,
ensureIsLocalChannel,
videoChannelsListValidator,
videoChannelStatsValidator
}
if (areValidationErrors(req, res)) return

if (!CONFIG.IMPORT.VIDEOS.HTTP.ENABLED) {
res.fail({
status: HttpStatusCode.FORBIDDEN_403,
message: 'Channel import is impossible as video upload via HTTP is not enabled on the server'
})
}

return next()
}
]

// ---------------------------------------------------------------------------

Expand Down
Loading

0 comments on commit 9dc5088

Please sign in to comment.