aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/api/index.ts4
-rw-r--r--server/controllers/api/users/index.ts12
-rw-r--r--server/controllers/api/users/token.ts5
-rw-r--r--server/controllers/api/videos/index.ts13
-rw-r--r--server/controllers/api/videos/upload.ts7
-rw-r--r--server/controllers/api/videos/view.ts2
-rw-r--r--server/controllers/feeds.ts10
-rw-r--r--server/controllers/lazy-static.ts21
-rw-r--r--server/controllers/services.ts44
9 files changed, 90 insertions, 28 deletions
diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts
index 5f49336b1..d1d4ef765 100644
--- a/server/controllers/api/index.ts
+++ b/server/controllers/api/index.ts
@@ -1,6 +1,6 @@
1import cors from 'cors' 1import cors from 'cors'
2import express from 'express' 2import express from 'express'
3import RateLimit from 'express-rate-limit' 3import { buildRateLimiter } from '@server/middlewares'
4import { HttpStatusCode } from '../../../shared/models' 4import { HttpStatusCode } from '../../../shared/models'
5import { badRequest } from '../../helpers/express-utils' 5import { badRequest } from '../../helpers/express-utils'
6import { CONFIG } from '../../initializers/config' 6import { CONFIG } from '../../initializers/config'
@@ -29,7 +29,7 @@ apiRouter.use(cors({
29 credentials: true 29 credentials: true
30})) 30}))
31 31
32const apiRateLimiter = RateLimit({ 32const apiRateLimiter = buildRateLimiter({
33 windowMs: CONFIG.RATES_LIMIT.API.WINDOW_MS, 33 windowMs: CONFIG.RATES_LIMIT.API.WINDOW_MS,
34 max: CONFIG.RATES_LIMIT.API.MAX 34 max: CONFIG.RATES_LIMIT.API.MAX
35}) 35})
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts
index 8a06bfe93..46e80d56d 100644
--- a/server/controllers/api/users/index.ts
+++ b/server/controllers/api/users/index.ts
@@ -1,5 +1,4 @@
1import express from 'express' 1import express from 'express'
2import RateLimit from 'express-rate-limit'
3import { tokensRouter } from '@server/controllers/api/users/token' 2import { tokensRouter } from '@server/controllers/api/users/token'
4import { Hooks } from '@server/lib/plugins/hooks' 3import { Hooks } from '@server/lib/plugins/hooks'
5import { OAuthTokenModel } from '@server/models/oauth/oauth-token' 4import { OAuthTokenModel } from '@server/models/oauth/oauth-token'
@@ -17,9 +16,11 @@ import { Notifier } from '../../../lib/notifier'
17import { Redis } from '../../../lib/redis' 16import { Redis } from '../../../lib/redis'
18import { buildUser, createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user' 17import { buildUser, createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user'
19import { 18import {
19 adminUsersSortValidator,
20 asyncMiddleware, 20 asyncMiddleware,
21 asyncRetryTransactionMiddleware, 21 asyncRetryTransactionMiddleware,
22 authenticate, 22 authenticate,
23 buildRateLimiter,
23 ensureUserHasRight, 24 ensureUserHasRight,
24 ensureUserRegistrationAllowed, 25 ensureUserRegistrationAllowed,
25 ensureUserRegistrationAllowedForIP, 26 ensureUserRegistrationAllowedForIP,
@@ -32,7 +33,6 @@ import {
32 usersListValidator, 33 usersListValidator,
33 usersRegisterValidator, 34 usersRegisterValidator,
34 usersRemoveValidator, 35 usersRemoveValidator,
35 usersSortValidator,
36 usersUpdateValidator 36 usersUpdateValidator
37} from '../../../middlewares' 37} from '../../../middlewares'
38import { 38import {
@@ -54,13 +54,13 @@ import { myVideoPlaylistsRouter } from './my-video-playlists'
54 54
55const auditLogger = auditLoggerFactory('users') 55const auditLogger = auditLoggerFactory('users')
56 56
57const signupRateLimiter = RateLimit({ 57const signupRateLimiter = buildRateLimiter({
58 windowMs: CONFIG.RATES_LIMIT.SIGNUP.WINDOW_MS, 58 windowMs: CONFIG.RATES_LIMIT.SIGNUP.WINDOW_MS,
59 max: CONFIG.RATES_LIMIT.SIGNUP.MAX, 59 max: CONFIG.RATES_LIMIT.SIGNUP.MAX,
60 skipFailedRequests: true 60 skipFailedRequests: true
61}) 61})
62 62
63const askSendEmailLimiter = RateLimit({ 63const askSendEmailLimiter = buildRateLimiter({
64 windowMs: CONFIG.RATES_LIMIT.ASK_SEND_EMAIL.WINDOW_MS, 64 windowMs: CONFIG.RATES_LIMIT.ASK_SEND_EMAIL.WINDOW_MS,
65 max: CONFIG.RATES_LIMIT.ASK_SEND_EMAIL.MAX 65 max: CONFIG.RATES_LIMIT.ASK_SEND_EMAIL.MAX
66}) 66})
@@ -84,7 +84,7 @@ usersRouter.get('/',
84 authenticate, 84 authenticate,
85 ensureUserHasRight(UserRight.MANAGE_USERS), 85 ensureUserHasRight(UserRight.MANAGE_USERS),
86 paginationValidator, 86 paginationValidator,
87 usersSortValidator, 87 adminUsersSortValidator,
88 setDefaultSort, 88 setDefaultSort,
89 setDefaultPagination, 89 setDefaultPagination,
90 usersListValidator, 90 usersListValidator,
@@ -277,7 +277,7 @@ async function autocompleteUsers (req: express.Request, res: express.Response) {
277} 277}
278 278
279async function listUsers (req: express.Request, res: express.Response) { 279async function listUsers (req: express.Request, res: express.Response) {
280 const resultList = await UserModel.listForApi({ 280 const resultList = await UserModel.listForAdminApi({
281 start: req.query.start, 281 start: req.query.start,
282 count: req.query.count, 282 count: req.query.count,
283 sort: req.query.sort, 283 sort: req.query.sort,
diff --git a/server/controllers/api/users/token.ts b/server/controllers/api/users/token.ts
index 258b50fe9..012a49791 100644
--- a/server/controllers/api/users/token.ts
+++ b/server/controllers/api/users/token.ts
@@ -1,18 +1,17 @@
1import express from 'express' 1import express from 'express'
2import RateLimit from 'express-rate-limit'
3import { logger } from '@server/helpers/logger' 2import { logger } from '@server/helpers/logger'
4import { CONFIG } from '@server/initializers/config' 3import { CONFIG } from '@server/initializers/config'
5import { getAuthNameFromRefreshGrant, getBypassFromExternalAuth, getBypassFromPasswordGrant } from '@server/lib/auth/external-auth' 4import { getAuthNameFromRefreshGrant, getBypassFromExternalAuth, getBypassFromPasswordGrant } from '@server/lib/auth/external-auth'
6import { handleOAuthToken } from '@server/lib/auth/oauth' 5import { handleOAuthToken } from '@server/lib/auth/oauth'
7import { BypassLogin, revokeToken } from '@server/lib/auth/oauth-model' 6import { BypassLogin, revokeToken } from '@server/lib/auth/oauth-model'
8import { Hooks } from '@server/lib/plugins/hooks' 7import { Hooks } from '@server/lib/plugins/hooks'
9import { asyncMiddleware, authenticate, openapiOperationDoc } from '@server/middlewares' 8import { asyncMiddleware, authenticate, buildRateLimiter, openapiOperationDoc } from '@server/middlewares'
10import { buildUUID } from '@shared/extra-utils' 9import { buildUUID } from '@shared/extra-utils'
11import { ScopedToken } from '@shared/models/users/user-scoped-token' 10import { ScopedToken } from '@shared/models/users/user-scoped-token'
12 11
13const tokensRouter = express.Router() 12const tokensRouter = express.Router()
14 13
15const loginRateLimiter = RateLimit({ 14const loginRateLimiter = buildRateLimiter({
16 windowMs: CONFIG.RATES_LIMIT.LOGIN.WINDOW_MS, 15 windowMs: CONFIG.RATES_LIMIT.LOGIN.WINDOW_MS,
17 max: CONFIG.RATES_LIMIT.LOGIN.MAX 16 max: CONFIG.RATES_LIMIT.LOGIN.MAX
18}) 17})
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index be233722c..d4e08293e 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -26,6 +26,7 @@ import {
26 setDefaultVideosSort, 26 setDefaultVideosSort,
27 videosCustomGetValidator, 27 videosCustomGetValidator,
28 videosGetValidator, 28 videosGetValidator,
29 videoSourceGetValidator,
29 videosRemoveValidator, 30 videosRemoveValidator,
30 videosSortValidator 31 videosSortValidator
31} from '../../../middlewares' 32} from '../../../middlewares'
@@ -96,6 +97,14 @@ videosRouter.get('/:id/description',
96 asyncMiddleware(videosGetValidator), 97 asyncMiddleware(videosGetValidator),
97 asyncMiddleware(getVideoDescription) 98 asyncMiddleware(getVideoDescription)
98) 99)
100
101videosRouter.get('/:id/source',
102 openapiOperationDoc({ operationId: 'getVideoSource' }),
103 authenticate,
104 asyncMiddleware(videoSourceGetValidator),
105 getVideoSource
106)
107
99videosRouter.get('/:id', 108videosRouter.get('/:id',
100 openapiOperationDoc({ operationId: 'getVideo' }), 109 openapiOperationDoc({ operationId: 'getVideo' }),
101 optionalAuthenticate, 110 optionalAuthenticate,
@@ -155,6 +164,10 @@ async function getVideoDescription (req: express.Request, res: express.Response)
155 return res.json({ description }) 164 return res.json({ description })
156} 165}
157 166
167function getVideoSource (req: express.Request, res: express.Response) {
168 return res.json(res.locals.videoSource.toFormattedJSON())
169}
170
158async function listVideos (req: express.Request, res: express.Response) { 171async function listVideos (req: express.Request, res: express.Response) {
159 const serverActor = await getServerActor() 172 const serverActor = await getServerActor()
160 173
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts
index 3afbedbb2..c5890691e 100644
--- a/server/controllers/api/videos/upload.ts
+++ b/server/controllers/api/videos/upload.ts
@@ -44,6 +44,7 @@ import {
44import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' 44import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
45import { VideoModel } from '../../../models/video/video' 45import { VideoModel } from '../../../models/video/video'
46import { VideoFileModel } from '../../../models/video/video-file' 46import { VideoFileModel } from '../../../models/video/video-file'
47import { VideoSourceModel } from '@server/models/video/video-source'
47 48
48const lTags = loggerTagsFactory('api', 'video') 49const lTags = loggerTagsFactory('api', 'video')
49const auditLogger = auditLoggerFactory('videos') 50const auditLogger = auditLoggerFactory('videos')
@@ -151,6 +152,7 @@ async function addVideo (options: {
151 video.url = getLocalVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object 152 video.url = getLocalVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object
152 153
153 const videoFile = await buildNewFile(videoPhysicalFile) 154 const videoFile = await buildNewFile(videoPhysicalFile)
155 const originalFilename = videoPhysicalFile.originalname
154 156
155 // Move physical file 157 // Move physical file
156 const destination = VideoPathManager.Instance.getFSVideoFileOutputPath(video, videoFile) 158 const destination = VideoPathManager.Instance.getFSVideoFileOutputPath(video, videoFile)
@@ -181,6 +183,11 @@ async function addVideo (options: {
181 183
182 video.VideoFiles = [ videoFile ] 184 video.VideoFiles = [ videoFile ]
183 185
186 await VideoSourceModel.create({
187 filename: originalFilename,
188 videoId: video.id
189 }, { transaction: t })
190
184 await setVideoTags({ video, tags: videoInfo.tags, transaction: t }) 191 await setVideoTags({ video, tags: videoInfo.tags, transaction: t })
185 192
186 // Schedule an update in the future? 193 // Schedule an update in the future?
diff --git a/server/controllers/api/videos/view.ts b/server/controllers/api/videos/view.ts
index db1091f2d..dee1ec67c 100644
--- a/server/controllers/api/videos/view.ts
+++ b/server/controllers/api/videos/view.ts
@@ -26,7 +26,7 @@ export {
26// --------------------------------------------------------------------------- 26// ---------------------------------------------------------------------------
27 27
28async function viewVideo (req: express.Request, res: express.Response) { 28async function viewVideo (req: express.Request, res: express.Response) {
29 const video = res.locals.onlyVideo 29 const video = res.locals.onlyImmutableVideo
30 30
31 const body = req.body as VideoView 31 const body = req.body as VideoView
32 32
diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts
index c929a6726..9eb31ed93 100644
--- a/server/controllers/feeds.ts
+++ b/server/controllers/feeds.ts
@@ -1,13 +1,13 @@
1import express from 'express' 1import express from 'express'
2import { Feed } from '@peertube/feed'
3import { extname } from 'path' 2import { extname } from 'path'
3import { Feed } from '@peertube/feed'
4import { mdToOneLinePlainText, toSafeHtml } from '@server/helpers/markdown' 4import { mdToOneLinePlainText, toSafeHtml } from '@server/helpers/markdown'
5import { getServerActor } from '@server/models/application/application' 5import { getServerActor } from '@server/models/application/application'
6import { getCategoryLabel } from '@server/models/video/formatter/video-format-utils' 6import { getCategoryLabel } from '@server/models/video/formatter/video-format-utils'
7import { VideoInclude } from '@shared/models' 7import { VideoInclude } from '@shared/models'
8import { buildNSFWFilter } from '../helpers/express-utils' 8import { buildNSFWFilter } from '../helpers/express-utils'
9import { CONFIG } from '../initializers/config' 9import { CONFIG } from '../initializers/config'
10import { FEEDS, MIMETYPES, PREVIEWS_SIZE, ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants' 10import { MIMETYPES, PREVIEWS_SIZE, ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants'
11import { 11import {
12 asyncMiddleware, 12 asyncMiddleware,
13 commonVideosFiltersValidator, 13 commonVideosFiltersValidator,
@@ -76,7 +76,7 @@ async function generateVideoCommentsFeed (req: express.Request, res: express.Res
76 76
77 const comments = await VideoCommentModel.listForFeed({ 77 const comments = await VideoCommentModel.listForFeed({
78 start, 78 start,
79 count: FEEDS.COUNT, 79 count: CONFIG.FEEDS.COMMENTS.COUNT,
80 videoId: video ? video.id : undefined, 80 videoId: video ? video.id : undefined,
81 accountId: account ? account.id : undefined, 81 accountId: account ? account.id : undefined,
82 videoChannelId: videoChannel ? videoChannel.id : undefined 82 videoChannelId: videoChannel ? videoChannel.id : undefined
@@ -166,7 +166,7 @@ async function generateVideoFeed (req: express.Request, res: express.Response) {
166 const server = await getServerActor() 166 const server = await getServerActor()
167 const { data } = await VideoModel.listForApi({ 167 const { data } = await VideoModel.listForApi({
168 start, 168 start,
169 count: FEEDS.COUNT, 169 count: CONFIG.FEEDS.VIDEOS.COUNT,
170 sort: req.query.sort, 170 sort: req.query.sort,
171 displayOnlyForFollower: { 171 displayOnlyForFollower: {
172 actorId: server.id, 172 actorId: server.id,
@@ -202,7 +202,7 @@ async function generateVideoFeedForSubscriptions (req: express.Request, res: exp
202 202
203 const { data } = await VideoModel.listForApi({ 203 const { data } = await VideoModel.listForApi({
204 start, 204 start,
205 count: FEEDS.COUNT, 205 count: CONFIG.FEEDS.VIDEOS.COUNT,
206 sort: req.query.sort, 206 sort: req.query.sort,
207 nsfw, 207 nsfw,
208 208
diff --git a/server/controllers/lazy-static.ts b/server/controllers/lazy-static.ts
index 55bf02660..8a180b5bc 100644
--- a/server/controllers/lazy-static.ts
+++ b/server/controllers/lazy-static.ts
@@ -1,9 +1,10 @@
1import cors from 'cors' 1import cors from 'cors'
2import express from 'express' 2import express from 'express'
3import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' 3import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
4import { MActorImage } from '@server/types/models'
4import { HttpStatusCode } from '../../shared/models/http/http-error-codes' 5import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
5import { logger } from '../helpers/logger' 6import { logger } from '../helpers/logger'
6import { LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' 7import { ACTOR_IMAGES_SIZE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants'
7import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache' 8import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache'
8import { actorImagePathUnsafeCache, pushActorImageProcessInQueue } from '../lib/local-actor' 9import { actorImagePathUnsafeCache, pushActorImageProcessInQueue } from '../lib/local-actor'
9import { asyncMiddleware } from '../middlewares' 10import { asyncMiddleware } from '../middlewares'
@@ -67,10 +68,7 @@ async function getActorImage (req: express.Request, res: express.Response, next:
67 await pushActorImageProcessInQueue({ 68 await pushActorImageProcessInQueue({
68 filename: image.filename, 69 filename: image.filename,
69 fileUrl: image.fileUrl, 70 fileUrl: image.fileUrl,
70 size: { 71 size: getActorImageSize(image),
71 height: image.height,
72 width: image.width
73 },
74 type: image.type 72 type: image.type
75 }) 73 })
76 } catch (err) { 74 } catch (err) {
@@ -94,7 +92,7 @@ async function getActorImage (req: express.Request, res: express.Response, next:
94 if (err.status === HttpStatusCode.NOT_FOUND_404 && !image.isOwned()) { 92 if (err.status === HttpStatusCode.NOT_FOUND_404 && !image.isOwned()) {
95 logger.error('Cannot lazy serve actor image %s.', filename, { err }) 93 logger.error('Cannot lazy serve actor image %s.', filename, { err })
96 94
97 actorImagePathUnsafeCache.del(filename) 95 actorImagePathUnsafeCache.delete(filename)
98 96
99 image.onDisk = false 97 image.onDisk = false
100 image.save() 98 image.save()
@@ -105,6 +103,17 @@ async function getActorImage (req: express.Request, res: express.Response, next:
105 }) 103 })
106} 104}
107 105
106function getActorImageSize (image: MActorImage): { width: number, height: number } {
107 if (image.width && image.height) {
108 return {
109 height: image.height,
110 width: image.width
111 }
112 }
113
114 return ACTOR_IMAGES_SIZE[image.type][0]
115}
116
108async function getPreview (req: express.Request, res: express.Response) { 117async function getPreview (req: express.Request, res: express.Response) {
109 const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename) 118 const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename)
110 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() 119 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end()
diff --git a/server/controllers/services.ts b/server/controllers/services.ts
index 9151e1b04..70d08ab69 100644
--- a/server/controllers/services.ts
+++ b/server/controllers/services.ts
@@ -1,9 +1,9 @@
1import express from 'express' 1import express from 'express'
2import { EMBED_SIZE, PREVIEWS_SIZE, WEBSERVER, THUMBNAILS_SIZE } from '../initializers/constants'
3import { asyncMiddleware, oembedValidator } from '../middlewares'
4import { accountNameWithHostGetValidator } from '../middlewares/validators'
5import { MChannelSummary } from '@server/types/models' 2import { MChannelSummary } from '@server/types/models'
6import { escapeHTML } from '@shared/core-utils/renderer' 3import { escapeHTML } from '@shared/core-utils/renderer'
4import { EMBED_SIZE, PREVIEWS_SIZE, THUMBNAILS_SIZE, WEBSERVER } from '../initializers/constants'
5import { asyncMiddleware, oembedValidator } from '../middlewares'
6import { accountNameWithHostGetValidator } from '../middlewares/validators'
7 7
8const servicesRouter = express.Router() 8const servicesRouter = express.Router()
9 9
@@ -36,7 +36,7 @@ function generatePlaylistOEmbed (req: express.Request, res: express.Response) {
36 const json = buildOEmbed({ 36 const json = buildOEmbed({
37 channel: playlist.VideoChannel, 37 channel: playlist.VideoChannel,
38 title: playlist.name, 38 title: playlist.name,
39 embedPath: playlist.getEmbedStaticPath(), 39 embedPath: playlist.getEmbedStaticPath() + buildPlayerURLQuery(req.query.url),
40 previewPath: playlist.getThumbnailStaticPath(), 40 previewPath: playlist.getThumbnailStaticPath(),
41 previewSize: THUMBNAILS_SIZE, 41 previewSize: THUMBNAILS_SIZE,
42 req 42 req
@@ -51,7 +51,7 @@ function generateVideoOEmbed (req: express.Request, res: express.Response) {
51 const json = buildOEmbed({ 51 const json = buildOEmbed({
52 channel: video.VideoChannel, 52 channel: video.VideoChannel,
53 title: video.name, 53 title: video.name,
54 embedPath: video.getEmbedStaticPath(), 54 embedPath: video.getEmbedStaticPath() + buildPlayerURLQuery(req.query.url),
55 previewPath: video.getPreviewStaticPath(), 55 previewPath: video.getPreviewStaticPath(),
56 previewSize: PREVIEWS_SIZE, 56 previewSize: PREVIEWS_SIZE,
57 req 57 req
@@ -60,6 +60,40 @@ function generateVideoOEmbed (req: express.Request, res: express.Response) {
60 return res.json(json) 60 return res.json(json)
61} 61}
62 62
63function buildPlayerURLQuery (inputQueryUrl: string) {
64 const allowedParameters = new Set([
65 'start',
66 'stop',
67 'loop',
68 'autoplay',
69 'muted',
70 'controls',
71 'controlBar',
72 'title',
73 'api',
74 'warningTitle',
75 'peertubeLink',
76 'p2p',
77 'subtitle',
78 'bigPlayBackgroundColor',
79 'mode',
80 'foregroundColor'
81 ])
82
83 const params = new URLSearchParams()
84
85 new URL(inputQueryUrl).searchParams.forEach((v, k) => {
86 if (allowedParameters.has(k)) {
87 params.append(k, v)
88 }
89 })
90
91 const stringQuery = params.toString()
92 if (!stringQuery) return ''
93
94 return '?' + stringQuery
95}
96
63function buildOEmbed (options: { 97function buildOEmbed (options: {
64 req: express.Request 98 req: express.Request
65 title: string 99 title: string