diff options
Diffstat (limited to 'server/controllers/api')
-rw-r--r-- | server/controllers/api/accounts.ts | 16 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/users/index.ts | 37 | ||||
-rw-r--r-- | server/controllers/api/users/me.ts | 16 | ||||
-rw-r--r-- | server/controllers/api/video-channel.ts | 37 | ||||
-rw-r--r-- | server/controllers/api/video-playlist.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 54 |
7 files changed, 127 insertions, 45 deletions
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 8d4db1e75..5a1d652f2 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -16,7 +16,8 @@ import { | |||
16 | accountNameWithHostGetValidator, | 16 | accountNameWithHostGetValidator, |
17 | accountsSortValidator, | 17 | accountsSortValidator, |
18 | ensureAuthUserOwnsAccountValidator, | 18 | ensureAuthUserOwnsAccountValidator, |
19 | videosSortValidator | 19 | videosSortValidator, |
20 | videoChannelsSortValidator | ||
20 | } from '../../middlewares/validators' | 21 | } from '../../middlewares/validators' |
21 | import { AccountModel } from '../../models/account/account' | 22 | import { AccountModel } from '../../models/account/account' |
22 | import { AccountVideoRateModel } from '../../models/account/account-video-rate' | 23 | import { AccountVideoRateModel } from '../../models/account/account-video-rate' |
@@ -56,6 +57,10 @@ accountsRouter.get('/:accountName/videos', | |||
56 | 57 | ||
57 | accountsRouter.get('/:accountName/video-channels', | 58 | accountsRouter.get('/:accountName/video-channels', |
58 | asyncMiddleware(accountNameWithHostGetValidator), | 59 | asyncMiddleware(accountNameWithHostGetValidator), |
60 | paginationValidator, | ||
61 | videoChannelsSortValidator, | ||
62 | setDefaultSort, | ||
63 | setDefaultPagination, | ||
59 | asyncMiddleware(listAccountChannels) | 64 | asyncMiddleware(listAccountChannels) |
60 | ) | 65 | ) |
61 | 66 | ||
@@ -108,7 +113,14 @@ async function listAccounts (req: express.Request, res: express.Response) { | |||
108 | } | 113 | } |
109 | 114 | ||
110 | async function listAccountChannels (req: express.Request, res: express.Response) { | 115 | async function listAccountChannels (req: express.Request, res: express.Response) { |
111 | const resultList = await VideoChannelModel.listByAccount(res.locals.account.id) | 116 | const options = { |
117 | accountId: res.locals.account.id, | ||
118 | start: req.query.start, | ||
119 | count: req.query.count, | ||
120 | sort: req.query.sort | ||
121 | } | ||
122 | |||
123 | const resultList = await VideoChannelModel.listByAccount(options) | ||
112 | 124 | ||
113 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 125 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
114 | } | 126 | } |
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 40012c03b..1d12f701b 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -51,7 +51,7 @@ async function getConfig (req: express.Request, res: express.Response) { | |||
51 | if (serverCommit === undefined) serverCommit = await getServerCommit() | 51 | if (serverCommit === undefined) serverCommit = await getServerCommit() |
52 | 52 | ||
53 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) | 53 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) |
54 | .filter(key => CONFIG.TRANSCODING.ENABLED === CONFIG.TRANSCODING.RESOLUTIONS[key] === true) | 54 | .filter(key => CONFIG.TRANSCODING.ENABLED && CONFIG.TRANSCODING.RESOLUTIONS[key] === true) |
55 | .map(r => parseInt(r, 10)) | 55 | .map(r => parseInt(r, 10)) |
56 | 56 | ||
57 | const json: ServerConfig = { | 57 | const json: ServerConfig = { |
@@ -255,13 +255,15 @@ function customConfig (): CustomConfig { | |||
255 | transcoding: { | 255 | transcoding: { |
256 | enabled: CONFIG.TRANSCODING.ENABLED, | 256 | enabled: CONFIG.TRANSCODING.ENABLED, |
257 | allowAdditionalExtensions: CONFIG.TRANSCODING.ALLOW_ADDITIONAL_EXTENSIONS, | 257 | allowAdditionalExtensions: CONFIG.TRANSCODING.ALLOW_ADDITIONAL_EXTENSIONS, |
258 | allowAudioFiles: CONFIG.TRANSCODING.ALLOW_AUDIO_FILES, | ||
258 | threads: CONFIG.TRANSCODING.THREADS, | 259 | threads: CONFIG.TRANSCODING.THREADS, |
259 | resolutions: { | 260 | resolutions: { |
260 | '240p': CONFIG.TRANSCODING.RESOLUTIONS[ '240p' ], | 261 | '240p': CONFIG.TRANSCODING.RESOLUTIONS[ '240p' ], |
261 | '360p': CONFIG.TRANSCODING.RESOLUTIONS[ '360p' ], | 262 | '360p': CONFIG.TRANSCODING.RESOLUTIONS[ '360p' ], |
262 | '480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ], | 263 | '480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ], |
263 | '720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ], | 264 | '720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ], |
264 | '1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ] | 265 | '1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ], |
266 | '2160p': CONFIG.TRANSCODING.RESOLUTIONS[ '2160p' ] | ||
265 | }, | 267 | }, |
266 | hls: { | 268 | hls: { |
267 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | 269 | enabled: CONFIG.TRANSCODING.HLS.ENABLED |
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index 0aafba66e..c1d72087c 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts | |||
@@ -6,7 +6,7 @@ import { getFormattedObjects } from '../../../helpers/utils' | |||
6 | import { RATES_LIMIT, WEBSERVER } from '../../../initializers/constants' | 6 | import { RATES_LIMIT, WEBSERVER } from '../../../initializers/constants' |
7 | import { Emailer } from '../../../lib/emailer' | 7 | import { Emailer } from '../../../lib/emailer' |
8 | import { Redis } from '../../../lib/redis' | 8 | import { Redis } from '../../../lib/redis' |
9 | import { createUserAccountAndChannelAndPlaylist } from '../../../lib/user' | 9 | import { createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user' |
10 | import { | 10 | import { |
11 | asyncMiddleware, | 11 | asyncMiddleware, |
12 | asyncRetryTransactionMiddleware, | 12 | asyncRetryTransactionMiddleware, |
@@ -46,14 +46,18 @@ import { mySubscriptionsRouter } from './my-subscriptions' | |||
46 | import { CONFIG } from '../../../initializers/config' | 46 | import { CONFIG } from '../../../initializers/config' |
47 | import { sequelizeTypescript } from '../../../initializers/database' | 47 | import { sequelizeTypescript } from '../../../initializers/database' |
48 | import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' | 48 | import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' |
49 | import { UserRegister } from '../../../../shared/models/users/user-register.model' | ||
49 | 50 | ||
50 | const auditLogger = auditLoggerFactory('users') | 51 | const auditLogger = auditLoggerFactory('users') |
51 | 52 | ||
52 | const loginRateLimiter = new RateLimit({ | 53 | // FIXME: https://github.com/nfriedly/express-rate-limit/issues/138 |
54 | // @ts-ignore | ||
55 | const loginRateLimiter = RateLimit({ | ||
53 | windowMs: RATES_LIMIT.LOGIN.WINDOW_MS, | 56 | windowMs: RATES_LIMIT.LOGIN.WINDOW_MS, |
54 | max: RATES_LIMIT.LOGIN.MAX | 57 | max: RATES_LIMIT.LOGIN.MAX |
55 | }) | 58 | }) |
56 | 59 | ||
60 | // @ts-ignore | ||
57 | const askSendEmailLimiter = new RateLimit({ | 61 | const askSendEmailLimiter = new RateLimit({ |
58 | windowMs: RATES_LIMIT.ASK_SEND_EMAIL.WINDOW_MS, | 62 | windowMs: RATES_LIMIT.ASK_SEND_EMAIL.WINDOW_MS, |
59 | max: RATES_LIMIT.ASK_SEND_EMAIL.MAX | 63 | max: RATES_LIMIT.ASK_SEND_EMAIL.MAX |
@@ -143,7 +147,7 @@ usersRouter.post('/:id/reset-password', | |||
143 | usersRouter.post('/ask-send-verify-email', | 147 | usersRouter.post('/ask-send-verify-email', |
144 | askSendEmailLimiter, | 148 | askSendEmailLimiter, |
145 | asyncMiddleware(usersAskSendVerifyEmailValidator), | 149 | asyncMiddleware(usersAskSendVerifyEmailValidator), |
146 | asyncMiddleware(askSendVerifyUserEmail) | 150 | asyncMiddleware(reSendVerifyUserEmail) |
147 | ) | 151 | ) |
148 | 152 | ||
149 | usersRouter.post('/:id/verify-email', | 153 | usersRouter.post('/:id/verify-email', |
@@ -180,7 +184,7 @@ async function createUser (req: express.Request, res: express.Response) { | |||
180 | adminFlags: body.adminFlags || UserAdminFlag.NONE | 184 | adminFlags: body.adminFlags || UserAdminFlag.NONE |
181 | }) | 185 | }) |
182 | 186 | ||
183 | const { user, account } = await createUserAccountAndChannelAndPlaylist(userToCreate) | 187 | const { user, account } = await createUserAccountAndChannelAndPlaylist({ userToCreate: userToCreate }) |
184 | 188 | ||
185 | auditLogger.create(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON())) | 189 | auditLogger.create(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON())) |
186 | logger.info('User %s with its channel and account created.', body.username) | 190 | logger.info('User %s with its channel and account created.', body.username) |
@@ -189,15 +193,14 @@ async function createUser (req: express.Request, res: express.Response) { | |||
189 | user: { | 193 | user: { |
190 | id: user.id, | 194 | id: user.id, |
191 | account: { | 195 | account: { |
192 | id: account.id, | 196 | id: account.id |
193 | uuid: account.Actor.uuid | ||
194 | } | 197 | } |
195 | } | 198 | } |
196 | }).end() | 199 | }).end() |
197 | } | 200 | } |
198 | 201 | ||
199 | async function registerUser (req: express.Request, res: express.Response) { | 202 | async function registerUser (req: express.Request, res: express.Response) { |
200 | const body: UserCreate = req.body | 203 | const body: UserRegister = req.body |
201 | 204 | ||
202 | const userToCreate = new UserModel({ | 205 | const userToCreate = new UserModel({ |
203 | username: body.username, | 206 | username: body.username, |
@@ -211,7 +214,11 @@ async function registerUser (req: express.Request, res: express.Response) { | |||
211 | emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null | 214 | emailVerified: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION ? false : null |
212 | }) | 215 | }) |
213 | 216 | ||
214 | const { user } = await createUserAccountAndChannelAndPlaylist(userToCreate) | 217 | const { user } = await createUserAccountAndChannelAndPlaylist({ |
218 | userToCreate: userToCreate, | ||
219 | userDisplayName: body.displayName || undefined, | ||
220 | channelNames: body.channel | ||
221 | }) | ||
215 | 222 | ||
216 | auditLogger.create(body.username, new UserAuditView(user.toFormattedJSON())) | 223 | auditLogger.create(body.username, new UserAuditView(user.toFormattedJSON())) |
217 | logger.info('User %s with its channel and account registered.', body.username) | 224 | logger.info('User %s with its channel and account registered.', body.username) |
@@ -313,14 +320,7 @@ async function resetUserPassword (req: express.Request, res: express.Response) { | |||
313 | return res.status(204).end() | 320 | return res.status(204).end() |
314 | } | 321 | } |
315 | 322 | ||
316 | async function sendVerifyUserEmail (user: UserModel) { | 323 | async function reSendVerifyUserEmail (req: express.Request, res: express.Response) { |
317 | const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id) | ||
318 | const url = WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString | ||
319 | await Emailer.Instance.addVerifyEmailJob(user.email, url) | ||
320 | return | ||
321 | } | ||
322 | |||
323 | async function askSendVerifyUserEmail (req: express.Request, res: express.Response) { | ||
324 | const user = res.locals.user | 324 | const user = res.locals.user |
325 | 325 | ||
326 | await sendVerifyUserEmail(user) | 326 | await sendVerifyUserEmail(user) |
@@ -332,6 +332,11 @@ async function verifyUserEmail (req: express.Request, res: express.Response) { | |||
332 | const user = res.locals.user | 332 | const user = res.locals.user |
333 | user.emailVerified = true | 333 | user.emailVerified = true |
334 | 334 | ||
335 | if (req.body.isPendingEmail === true) { | ||
336 | user.email = user.pendingEmail | ||
337 | user.pendingEmail = null | ||
338 | } | ||
339 | |||
335 | await user.save() | 340 | await user.save() |
336 | 341 | ||
337 | return res.status(204).end() | 342 | return res.status(204).end() |
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index ddb239e7b..1750a02e9 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts | |||
@@ -28,6 +28,7 @@ import { VideoImportModel } from '../../../models/video/video-import' | |||
28 | import { AccountModel } from '../../../models/account/account' | 28 | import { AccountModel } from '../../../models/account/account' |
29 | import { CONFIG } from '../../../initializers/config' | 29 | import { CONFIG } from '../../../initializers/config' |
30 | import { sequelizeTypescript } from '../../../initializers/database' | 30 | import { sequelizeTypescript } from '../../../initializers/database' |
31 | import { sendVerifyUserEmail } from '../../../lib/user' | ||
31 | 32 | ||
32 | const auditLogger = auditLoggerFactory('users-me') | 33 | const auditLogger = auditLoggerFactory('users-me') |
33 | 34 | ||
@@ -171,17 +172,26 @@ async function deleteMe (req: express.Request, res: express.Response) { | |||
171 | 172 | ||
172 | async function updateMe (req: express.Request, res: express.Response) { | 173 | async function updateMe (req: express.Request, res: express.Response) { |
173 | const body: UserUpdateMe = req.body | 174 | const body: UserUpdateMe = req.body |
175 | let sendVerificationEmail = false | ||
174 | 176 | ||
175 | const user = res.locals.oauth.token.user | 177 | const user = res.locals.oauth.token.user |
176 | const oldUserAuditView = new UserAuditView(user.toFormattedJSON({})) | 178 | const oldUserAuditView = new UserAuditView(user.toFormattedJSON({})) |
177 | 179 | ||
178 | if (body.password !== undefined) user.password = body.password | 180 | if (body.password !== undefined) user.password = body.password |
179 | if (body.email !== undefined) user.email = body.email | ||
180 | if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy | 181 | if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy |
181 | if (body.webTorrentEnabled !== undefined) user.webTorrentEnabled = body.webTorrentEnabled | 182 | if (body.webTorrentEnabled !== undefined) user.webTorrentEnabled = body.webTorrentEnabled |
182 | if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo | 183 | if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo |
183 | if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled | 184 | if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled |
184 | 185 | ||
186 | if (body.email !== undefined) { | ||
187 | if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) { | ||
188 | user.pendingEmail = body.email | ||
189 | sendVerificationEmail = true | ||
190 | } else { | ||
191 | user.email = body.email | ||
192 | } | ||
193 | } | ||
194 | |||
185 | await sequelizeTypescript.transaction(async t => { | 195 | await sequelizeTypescript.transaction(async t => { |
186 | const userAccount = await AccountModel.load(user.Account.id) | 196 | const userAccount = await AccountModel.load(user.Account.id) |
187 | 197 | ||
@@ -196,6 +206,10 @@ async function updateMe (req: express.Request, res: express.Response) { | |||
196 | auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON({})), oldUserAuditView) | 206 | auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON({})), oldUserAuditView) |
197 | }) | 207 | }) |
198 | 208 | ||
209 | if (sendVerificationEmail === true) { | ||
210 | await sendVerifyUserEmail(user, true) | ||
211 | } | ||
212 | |||
199 | return res.sendStatus(204) | 213 | return res.sendStatus(204) |
200 | } | 214 | } |
201 | 215 | ||
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index 3d6dbfe70..81a03a62b 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts | |||
@@ -19,7 +19,7 @@ import { VideoChannelModel } from '../../models/video/video-channel' | |||
19 | import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../middlewares/validators' | 19 | import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../middlewares/validators' |
20 | import { sendUpdateActor } from '../../lib/activitypub/send' | 20 | import { sendUpdateActor } from '../../lib/activitypub/send' |
21 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' | 21 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' |
22 | import { createVideoChannel } from '../../lib/video-channel' | 22 | import { createVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel' |
23 | import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' | 23 | import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' |
24 | import { setAsyncActorKeys } from '../../lib/activitypub' | 24 | import { setAsyncActorKeys } from '../../lib/activitypub' |
25 | import { AccountModel } from '../../models/account/account' | 25 | import { AccountModel } from '../../models/account/account' |
@@ -143,15 +143,14 @@ async function addVideoChannel (req: express.Request, res: express.Response) { | |||
143 | }) | 143 | }) |
144 | 144 | ||
145 | setAsyncActorKeys(videoChannelCreated.Actor) | 145 | setAsyncActorKeys(videoChannelCreated.Actor) |
146 | .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err })) | 146 | .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.url, { err })) |
147 | 147 | ||
148 | auditLogger.create(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelCreated.toFormattedJSON())) | 148 | auditLogger.create(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelCreated.toFormattedJSON())) |
149 | logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) | 149 | logger.info('Video channel %s created.', videoChannelCreated.Actor.url) |
150 | 150 | ||
151 | return res.json({ | 151 | return res.json({ |
152 | videoChannel: { | 152 | videoChannel: { |
153 | id: videoChannelCreated.id, | 153 | id: videoChannelCreated.id |
154 | uuid: videoChannelCreated.Actor.uuid | ||
155 | } | 154 | } |
156 | }).end() | 155 | }).end() |
157 | } | 156 | } |
@@ -161,6 +160,7 @@ async function updateVideoChannel (req: express.Request, res: express.Response) | |||
161 | const videoChannelFieldsSave = videoChannelInstance.toJSON() | 160 | const videoChannelFieldsSave = videoChannelInstance.toJSON() |
162 | const oldVideoChannelAuditKeys = new VideoChannelAuditView(videoChannelInstance.toFormattedJSON()) | 161 | const oldVideoChannelAuditKeys = new VideoChannelAuditView(videoChannelInstance.toFormattedJSON()) |
163 | const videoChannelInfoToUpdate = req.body as VideoChannelUpdate | 162 | const videoChannelInfoToUpdate = req.body as VideoChannelUpdate |
163 | let doBulkVideoUpdate = false | ||
164 | 164 | ||
165 | try { | 165 | try { |
166 | await sequelizeTypescript.transaction(async t => { | 166 | await sequelizeTypescript.transaction(async t => { |
@@ -168,9 +168,18 @@ async function updateVideoChannel (req: express.Request, res: express.Response) | |||
168 | transaction: t | 168 | transaction: t |
169 | } | 169 | } |
170 | 170 | ||
171 | if (videoChannelInfoToUpdate.displayName !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.displayName) | 171 | if (videoChannelInfoToUpdate.displayName !== undefined) videoChannelInstance.name = videoChannelInfoToUpdate.displayName |
172 | if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description) | 172 | if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.description = videoChannelInfoToUpdate.description |
173 | if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support) | 173 | |
174 | if (videoChannelInfoToUpdate.support !== undefined) { | ||
175 | const oldSupportField = videoChannelInstance.support | ||
176 | videoChannelInstance.support = videoChannelInfoToUpdate.support | ||
177 | |||
178 | if (videoChannelInfoToUpdate.bulkVideosSupportUpdate === true && oldSupportField !== videoChannelInfoToUpdate.support) { | ||
179 | doBulkVideoUpdate = true | ||
180 | await VideoModel.bulkUpdateSupportField(videoChannelInstance, t) | ||
181 | } | ||
182 | } | ||
174 | 183 | ||
175 | const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) | 184 | const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) |
176 | await sendUpdateActor(videoChannelInstanceUpdated, t) | 185 | await sendUpdateActor(videoChannelInstanceUpdated, t) |
@@ -180,7 +189,8 @@ async function updateVideoChannel (req: express.Request, res: express.Response) | |||
180 | new VideoChannelAuditView(videoChannelInstanceUpdated.toFormattedJSON()), | 189 | new VideoChannelAuditView(videoChannelInstanceUpdated.toFormattedJSON()), |
181 | oldVideoChannelAuditKeys | 190 | oldVideoChannelAuditKeys |
182 | ) | 191 | ) |
183 | logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | 192 | |
193 | logger.info('Video channel %s updated.', videoChannelInstance.Actor.url) | ||
184 | }) | 194 | }) |
185 | } catch (err) { | 195 | } catch (err) { |
186 | logger.debug('Cannot update the video channel.', { err }) | 196 | logger.debug('Cannot update the video channel.', { err }) |
@@ -193,7 +203,12 @@ async function updateVideoChannel (req: express.Request, res: express.Response) | |||
193 | throw err | 203 | throw err |
194 | } | 204 | } |
195 | 205 | ||
196 | return res.type('json').status(204).end() | 206 | res.type('json').status(204).end() |
207 | |||
208 | // Don't process in a transaction, and after the response because it could be long | ||
209 | if (doBulkVideoUpdate) { | ||
210 | await federateAllVideosOfChannel(videoChannelInstance) | ||
211 | } | ||
197 | } | 212 | } |
198 | 213 | ||
199 | async function removeVideoChannel (req: express.Request, res: express.Response) { | 214 | async function removeVideoChannel (req: express.Request, res: express.Response) { |
@@ -205,7 +220,7 @@ async function removeVideoChannel (req: express.Request, res: express.Response) | |||
205 | await videoChannelInstance.destroy({ transaction: t }) | 220 | await videoChannelInstance.destroy({ transaction: t }) |
206 | 221 | ||
207 | auditLogger.delete(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelInstance.toFormattedJSON())) | 222 | auditLogger.delete(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelInstance.toFormattedJSON())) |
208 | logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | 223 | logger.info('Video channel %s deleted.', videoChannelInstance.Actor.url) |
209 | }) | 224 | }) |
210 | 225 | ||
211 | return res.type('json').status(204).end() | 226 | return res.type('json').status(204).end() |
diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts index a17136401..62490e63b 100644 --- a/server/controllers/api/video-playlist.ts +++ b/server/controllers/api/video-playlist.ts | |||
@@ -203,7 +203,9 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response) | |||
203 | const videoPlaylistInstance = res.locals.videoPlaylist | 203 | const videoPlaylistInstance = res.locals.videoPlaylist |
204 | const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON() | 204 | const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON() |
205 | const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate | 205 | const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate |
206 | |||
206 | const wasPrivatePlaylist = videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE | 207 | const wasPrivatePlaylist = videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE |
208 | const wasNotPrivatePlaylist = videoPlaylistInstance.privacy !== VideoPlaylistPrivacy.PRIVATE | ||
207 | 209 | ||
208 | const thumbnailField = req.files['thumbnailfile'] | 210 | const thumbnailField = req.files['thumbnailfile'] |
209 | const thumbnailModel = thumbnailField | 211 | const thumbnailModel = thumbnailField |
@@ -232,6 +234,10 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response) | |||
232 | 234 | ||
233 | if (videoPlaylistInfoToUpdate.privacy !== undefined) { | 235 | if (videoPlaylistInfoToUpdate.privacy !== undefined) { |
234 | videoPlaylistInstance.privacy = parseInt(videoPlaylistInfoToUpdate.privacy.toString(), 10) | 236 | videoPlaylistInstance.privacy = parseInt(videoPlaylistInfoToUpdate.privacy.toString(), 10) |
237 | |||
238 | if (wasNotPrivatePlaylist === true && videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE) { | ||
239 | await sendDeleteVideoPlaylist(videoPlaylistInstance, t) | ||
240 | } | ||
235 | } | 241 | } |
236 | 242 | ||
237 | const playlistUpdated = await videoPlaylistInstance.save(sequelizeOptions) | 243 | const playlistUpdated = await videoPlaylistInstance.save(sequelizeOptions) |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 1a18a8ae8..5ebd8fbc4 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -6,7 +6,14 @@ import { logger } from '../../../helpers/logger' | |||
6 | import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' | 6 | import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' |
7 | import { getFormattedObjects, getServerActor } from '../../../helpers/utils' | 7 | import { getFormattedObjects, getServerActor } from '../../../helpers/utils' |
8 | import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' | 8 | import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' |
9 | import { MIMETYPES, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers/constants' | 9 | import { |
10 | DEFAULT_AUDIO_RESOLUTION, | ||
11 | MIMETYPES, | ||
12 | VIDEO_CATEGORIES, | ||
13 | VIDEO_LANGUAGES, | ||
14 | VIDEO_LICENCES, | ||
15 | VIDEO_PRIVACIES | ||
16 | } from '../../../initializers/constants' | ||
10 | import { | 17 | import { |
11 | changeVideoChannelShare, | 18 | changeVideoChannelShare, |
12 | federateVideoIfNeeded, | 19 | federateVideoIfNeeded, |
@@ -54,6 +61,7 @@ import { CONFIG } from '../../../initializers/config' | |||
54 | import { sequelizeTypescript } from '../../../initializers/database' | 61 | import { sequelizeTypescript } from '../../../initializers/database' |
55 | import { createVideoMiniatureFromExisting, generateVideoMiniature } from '../../../lib/thumbnail' | 62 | import { createVideoMiniatureFromExisting, generateVideoMiniature } from '../../../lib/thumbnail' |
56 | import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' | 63 | import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' |
64 | import { VideoTranscodingPayload } from '../../../lib/job-queue/handlers/video-transcoding' | ||
57 | 65 | ||
58 | const auditLogger = auditLoggerFactory('videos') | 66 | const auditLogger = auditLoggerFactory('videos') |
59 | const videosRouter = express.Router() | 67 | const videosRouter = express.Router() |
@@ -191,17 +199,17 @@ async function addVideo (req: express.Request, res: express.Response) { | |||
191 | const video = new VideoModel(videoData) | 199 | const video = new VideoModel(videoData) |
192 | video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object | 200 | video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object |
193 | 201 | ||
194 | // Build the file object | 202 | const videoFile = new VideoFileModel({ |
195 | const { videoFileResolution } = await getVideoFileResolution(videoPhysicalFile.path) | ||
196 | const fps = await getVideoFileFPS(videoPhysicalFile.path) | ||
197 | |||
198 | const videoFileData = { | ||
199 | extname: extname(videoPhysicalFile.filename), | 203 | extname: extname(videoPhysicalFile.filename), |
200 | resolution: videoFileResolution, | 204 | size: videoPhysicalFile.size |
201 | size: videoPhysicalFile.size, | 205 | }) |
202 | fps | 206 | |
207 | if (videoFile.isAudio()) { | ||
208 | videoFile.resolution = DEFAULT_AUDIO_RESOLUTION | ||
209 | } else { | ||
210 | videoFile.fps = await getVideoFileFPS(videoPhysicalFile.path) | ||
211 | videoFile.resolution = (await getVideoFileResolution(videoPhysicalFile.path)).videoFileResolution | ||
203 | } | 212 | } |
204 | const videoFile = new VideoFileModel(videoFileData) | ||
205 | 213 | ||
206 | // Move physical file | 214 | // Move physical file |
207 | const videoDir = CONFIG.STORAGE.VIDEOS_DIR | 215 | const videoDir = CONFIG.STORAGE.VIDEOS_DIR |
@@ -279,9 +287,21 @@ async function addVideo (req: express.Request, res: express.Response) { | |||
279 | 287 | ||
280 | if (video.state === VideoState.TO_TRANSCODE) { | 288 | if (video.state === VideoState.TO_TRANSCODE) { |
281 | // Put uuid because we don't have id auto incremented for now | 289 | // Put uuid because we don't have id auto incremented for now |
282 | const dataInput = { | 290 | let dataInput: VideoTranscodingPayload |
283 | videoUUID: videoCreated.uuid, | 291 | |
284 | isNewVideo: true | 292 | if (videoFile.isAudio()) { |
293 | dataInput = { | ||
294 | type: 'merge-audio' as 'merge-audio', | ||
295 | resolution: DEFAULT_AUDIO_RESOLUTION, | ||
296 | videoUUID: videoCreated.uuid, | ||
297 | isNewVideo: true | ||
298 | } | ||
299 | } else { | ||
300 | dataInput = { | ||
301 | type: 'optimize' as 'optimize', | ||
302 | videoUUID: videoCreated.uuid, | ||
303 | isNewVideo: true | ||
304 | } | ||
285 | } | 305 | } |
286 | 306 | ||
287 | await JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) | 307 | await JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) |
@@ -300,7 +320,9 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
300 | const videoFieldsSave = videoInstance.toJSON() | 320 | const videoFieldsSave = videoInstance.toJSON() |
301 | const oldVideoAuditView = new VideoAuditView(videoInstance.toFormattedDetailsJSON()) | 321 | const oldVideoAuditView = new VideoAuditView(videoInstance.toFormattedDetailsJSON()) |
302 | const videoInfoToUpdate: VideoUpdate = req.body | 322 | const videoInfoToUpdate: VideoUpdate = req.body |
323 | |||
303 | const wasPrivateVideo = videoInstance.privacy === VideoPrivacy.PRIVATE | 324 | const wasPrivateVideo = videoInstance.privacy === VideoPrivacy.PRIVATE |
325 | const wasNotPrivateVideo = videoInstance.privacy !== VideoPrivacy.PRIVATE | ||
304 | const wasUnlistedVideo = videoInstance.privacy === VideoPrivacy.UNLISTED | 326 | const wasUnlistedVideo = videoInstance.privacy === VideoPrivacy.UNLISTED |
305 | 327 | ||
306 | // Process thumbnail or create it from the video | 328 | // Process thumbnail or create it from the video |
@@ -336,9 +358,15 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
336 | const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10) | 358 | const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10) |
337 | videoInstance.privacy = newPrivacy | 359 | videoInstance.privacy = newPrivacy |
338 | 360 | ||
361 | // The video was private, and is not anymore -> publish it | ||
339 | if (wasPrivateVideo === true && newPrivacy !== VideoPrivacy.PRIVATE) { | 362 | if (wasPrivateVideo === true && newPrivacy !== VideoPrivacy.PRIVATE) { |
340 | videoInstance.publishedAt = new Date() | 363 | videoInstance.publishedAt = new Date() |
341 | } | 364 | } |
365 | |||
366 | // The video was not private, but now it is -> we need to unfederate it | ||
367 | if (wasNotPrivateVideo === true && newPrivacy === VideoPrivacy.PRIVATE) { | ||
368 | await VideoModel.sendDelete(videoInstance, { transaction: t }) | ||
369 | } | ||
342 | } | 370 | } |
343 | 371 | ||
344 | const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) | 372 | const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) |