diff options
author | Chocobozzz <me@florianbigard.com> | 2022-11-15 14:41:55 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-11-15 14:41:55 +0100 |
commit | 4638cd713dcdd007cd7f49b9a95fa62ac7823e7c (patch) | |
tree | 3e341c6ebbd1ce9e2bbacd72e7e3793e0bd467c2 /server | |
parent | 6bcb559fc9a491fc3ce83e7c077ee9dc742b1d63 (diff) | |
download | PeerTube-4638cd713dcdd007cd7f49b9a95fa62ac7823e7c.tar.gz PeerTube-4638cd713dcdd007cd7f49b9a95fa62ac7823e7c.tar.zst PeerTube-4638cd713dcdd007cd7f49b9a95fa62ac7823e7c.zip |
Don't inject untrusted input
Even if it's already checked in middlewares
It's better to have safe modals too
Diffstat (limited to 'server')
30 files changed, 89 insertions, 59 deletions
diff --git a/server/controllers/api/users/my-history.ts b/server/controllers/api/users/my-history.ts index bc5b40f59..e6d3e86ac 100644 --- a/server/controllers/api/users/my-history.ts +++ b/server/controllers/api/users/my-history.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { forceNumber } from '@shared/core-utils' | ||
1 | import express from 'express' | 2 | import express from 'express' |
2 | import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes' | 3 | import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes' |
3 | import { getFormattedObjects } from '../../../helpers/utils' | 4 | import { getFormattedObjects } from '../../../helpers/utils' |
@@ -55,7 +56,7 @@ async function listMyVideosHistory (req: express.Request, res: express.Response) | |||
55 | async function removeUserHistoryElement (req: express.Request, res: express.Response) { | 56 | async function removeUserHistoryElement (req: express.Request, res: express.Response) { |
56 | const user = res.locals.oauth.token.User | 57 | const user = res.locals.oauth.token.User |
57 | 58 | ||
58 | await UserVideoHistoryModel.removeUserHistoryElement(user, parseInt(req.params.videoId + '')) | 59 | await UserVideoHistoryModel.removeUserHistoryElement(user, forceNumber(req.params.videoId)) |
59 | 60 | ||
60 | return res.sendStatus(HttpStatusCode.NO_CONTENT_204) | 61 | return res.sendStatus(HttpStatusCode.NO_CONTENT_204) |
61 | } | 62 | } |
diff --git a/server/controllers/api/users/my-video-playlists.ts b/server/controllers/api/users/my-video-playlists.ts index 715717610..fbdbb7e50 100644 --- a/server/controllers/api/users/my-video-playlists.ts +++ b/server/controllers/api/users/my-video-playlists.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { uuidToShort } from '@shared/extra-utils' | ||
2 | import express from 'express' | 1 | import express from 'express' |
2 | import { forceNumber } from '@shared/core-utils' | ||
3 | import { uuidToShort } from '@shared/extra-utils' | ||
3 | import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model' | 4 | import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model' |
4 | import { asyncMiddleware, authenticate } from '../../../middlewares' | 5 | import { asyncMiddleware, authenticate } from '../../../middlewares' |
5 | import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists' | 6 | import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists' |
@@ -22,7 +23,7 @@ export { | |||
22 | // --------------------------------------------------------------------------- | 23 | // --------------------------------------------------------------------------- |
23 | 24 | ||
24 | async function doVideosInPlaylistExist (req: express.Request, res: express.Response) { | 25 | async function doVideosInPlaylistExist (req: express.Request, res: express.Response) { |
25 | const videoIds = req.query.videoIds.map(i => parseInt(i + '', 10)) | 26 | const videoIds = req.query.videoIds.map(i => forceNumber(i)) |
26 | const user = res.locals.oauth.token.User | 27 | const user = res.locals.oauth.token.User |
27 | 28 | ||
28 | const results = await VideoPlaylistModel.listPlaylistSummariesOf(user.Account.id, videoIds) | 29 | const results = await VideoPlaylistModel.listPlaylistSummariesOf(user.Account.id, videoIds) |
diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts index 1255d14c6..67fac3751 100644 --- a/server/controllers/api/video-playlist.ts +++ b/server/controllers/api/video-playlist.ts | |||
@@ -46,6 +46,7 @@ import { | |||
46 | import { AccountModel } from '../../models/account/account' | 46 | import { AccountModel } from '../../models/account/account' |
47 | import { VideoPlaylistModel } from '../../models/video/video-playlist' | 47 | import { VideoPlaylistModel } from '../../models/video/video-playlist' |
48 | import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element' | 48 | import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element' |
49 | import { forceNumber } from '@shared/core-utils' | ||
49 | 50 | ||
50 | const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT) | 51 | const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT) |
51 | 52 | ||
@@ -245,7 +246,7 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response) | |||
245 | if (videoPlaylistInfoToUpdate.description !== undefined) videoPlaylistInstance.description = videoPlaylistInfoToUpdate.description | 246 | if (videoPlaylistInfoToUpdate.description !== undefined) videoPlaylistInstance.description = videoPlaylistInfoToUpdate.description |
246 | 247 | ||
247 | if (videoPlaylistInfoToUpdate.privacy !== undefined) { | 248 | if (videoPlaylistInfoToUpdate.privacy !== undefined) { |
248 | videoPlaylistInstance.privacy = parseInt(videoPlaylistInfoToUpdate.privacy.toString(), 10) | 249 | videoPlaylistInstance.privacy = forceNumber(videoPlaylistInfoToUpdate.privacy) |
249 | 250 | ||
250 | if (wasNotPrivatePlaylist === true && videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE) { | 251 | if (wasNotPrivatePlaylist === true && videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE) { |
251 | await sendDeleteVideoPlaylist(videoPlaylistInstance, t) | 252 | await sendDeleteVideoPlaylist(videoPlaylistInstance, t) |
@@ -424,7 +425,7 @@ async function reorderVideosPlaylist (req: express.Request, res: express.Respons | |||
424 | 425 | ||
425 | const endOldPosition = oldPosition + reorderLength - 1 | 426 | const endOldPosition = oldPosition + reorderLength - 1 |
426 | // Insert our reordered elements in their place (update) | 427 | // Insert our reordered elements in their place (update) |
427 | await VideoPlaylistElementModel.reassignPositionOf(videoPlaylist.id, oldPosition, endOldPosition, newPosition, t) | 428 | await VideoPlaylistElementModel.reassignPositionOf({ videoPlaylistId: videoPlaylist.id, firstPosition: oldPosition, endPosition: endOldPosition, newPosition, transaction: t }) |
428 | 429 | ||
429 | // Decrease positions of elements after the old position of our ordered elements (decrease) | 430 | // Decrease positions of elements after the old position of our ordered elements (decrease) |
430 | await VideoPlaylistElementModel.increasePositionOf(videoPlaylist.id, oldPosition, -reorderLength, t) | 431 | await VideoPlaylistElementModel.increasePositionOf(videoPlaylist.id, oldPosition, -reorderLength, t) |
diff --git a/server/controllers/api/videos/update.ts b/server/controllers/api/videos/update.ts index 0a910379a..260dee2b9 100644 --- a/server/controllers/api/videos/update.ts +++ b/server/controllers/api/videos/update.ts | |||
@@ -19,6 +19,7 @@ import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosU | |||
19 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' | 19 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' |
20 | import { VideoModel } from '../../../models/video/video' | 20 | import { VideoModel } from '../../../models/video/video' |
21 | import { VideoPathManager } from '@server/lib/video-path-manager' | 21 | import { VideoPathManager } from '@server/lib/video-path-manager' |
22 | import { forceNumber } from '@shared/core-utils' | ||
22 | 23 | ||
23 | const lTags = loggerTagsFactory('api', 'video') | 24 | const lTags = loggerTagsFactory('api', 'video') |
24 | const auditLogger = auditLoggerFactory('videos') | 25 | const auditLogger = auditLoggerFactory('videos') |
@@ -174,7 +175,7 @@ async function updateVideoPrivacy (options: { | |||
174 | const { videoInstance, videoInfoToUpdate, hadPrivacyForFederation, transaction } = options | 175 | const { videoInstance, videoInfoToUpdate, hadPrivacyForFederation, transaction } = options |
175 | const isNewVideo = videoInstance.isNewVideo(videoInfoToUpdate.privacy) | 176 | const isNewVideo = videoInstance.isNewVideo(videoInfoToUpdate.privacy) |
176 | 177 | ||
177 | const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10) | 178 | const newPrivacy = forceNumber(videoInfoToUpdate.privacy) |
178 | setVideoPrivacy(videoInstance, newPrivacy) | 179 | setVideoPrivacy(videoInstance, newPrivacy) |
179 | 180 | ||
180 | // Unfederate the video if the new privacy is not compatible with federation | 181 | // Unfederate the video if the new privacy is not compatible with federation |
diff --git a/server/controllers/download.ts b/server/controllers/download.ts index d9f34109f..65b9a1d1b 100644 --- a/server/controllers/download.ts +++ b/server/controllers/download.ts | |||
@@ -5,7 +5,7 @@ import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache | |||
5 | import { Hooks } from '@server/lib/plugins/hooks' | 5 | import { Hooks } from '@server/lib/plugins/hooks' |
6 | import { VideoPathManager } from '@server/lib/video-path-manager' | 6 | import { VideoPathManager } from '@server/lib/video-path-manager' |
7 | import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' | 7 | import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' |
8 | import { addQueryParams } from '@shared/core-utils' | 8 | import { addQueryParams, forceNumber } from '@shared/core-utils' |
9 | import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models' | 9 | import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models' |
10 | import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants' | 10 | import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants' |
11 | import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares' | 11 | import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares' |
@@ -132,7 +132,7 @@ async function downloadHLSVideoFile (req: express.Request, res: express.Response | |||
132 | } | 132 | } |
133 | 133 | ||
134 | function getVideoFile (req: express.Request, files: MVideoFile[]) { | 134 | function getVideoFile (req: express.Request, files: MVideoFile[]) { |
135 | const resolution = parseInt(req.params.resolution, 10) | 135 | const resolution = forceNumber(req.params.resolution) |
136 | return files.find(f => f.resolution === resolution) | 136 | return files.find(f => f.resolution === resolution) |
137 | } | 137 | } |
138 | 138 | ||
diff --git a/server/controllers/services.ts b/server/controllers/services.ts index cabcbc00b..7c7ca1ff3 100644 --- a/server/controllers/services.ts +++ b/server/controllers/services.ts | |||
@@ -4,6 +4,7 @@ import { escapeHTML } from '@shared/core-utils/renderer' | |||
4 | import { EMBED_SIZE, PREVIEWS_SIZE, THUMBNAILS_SIZE, WEBSERVER } from '../initializers/constants' | 4 | import { EMBED_SIZE, PREVIEWS_SIZE, THUMBNAILS_SIZE, WEBSERVER } from '../initializers/constants' |
5 | import { asyncMiddleware, oembedValidator } from '../middlewares' | 5 | import { asyncMiddleware, oembedValidator } from '../middlewares' |
6 | import { accountNameWithHostGetValidator } from '../middlewares/validators' | 6 | import { accountNameWithHostGetValidator } from '../middlewares/validators' |
7 | import { forceNumber } from '@shared/core-utils' | ||
7 | 8 | ||
8 | const servicesRouter = express.Router() | 9 | const servicesRouter = express.Router() |
9 | 10 | ||
@@ -108,8 +109,8 @@ function buildOEmbed (options: { | |||
108 | const { req, previewSize, previewPath, title, channel, embedPath } = options | 109 | const { req, previewSize, previewPath, title, channel, embedPath } = options |
109 | 110 | ||
110 | const webserverUrl = WEBSERVER.URL | 111 | const webserverUrl = WEBSERVER.URL |
111 | const maxHeight = parseInt(req.query.maxheight, 10) | 112 | const maxHeight = forceNumber(req.query.maxheight) |
112 | const maxWidth = parseInt(req.query.maxwidth, 10) | 113 | const maxWidth = forceNumber(req.query.maxwidth) |
113 | 114 | ||
114 | const embedUrl = webserverUrl + embedPath | 115 | const embedUrl = webserverUrl + embedPath |
115 | const embedTitle = escapeHTML(title) | 116 | const embedTitle = escapeHTML(title) |
diff --git a/server/helpers/custom-validators/video-studio.ts b/server/helpers/custom-validators/video-studio.ts index 19e7906d5..68dfec8dd 100644 --- a/server/helpers/custom-validators/video-studio.ts +++ b/server/helpers/custom-validators/video-studio.ts | |||
@@ -4,6 +4,7 @@ import { buildTaskFileFieldname } from '@server/lib/video-studio' | |||
4 | import { VideoStudioTask } from '@shared/models' | 4 | import { VideoStudioTask } from '@shared/models' |
5 | import { isArray } from './misc' | 5 | import { isArray } from './misc' |
6 | import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos' | 6 | import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos' |
7 | import { forceNumber } from '@shared/core-utils' | ||
7 | 8 | ||
8 | function isValidStudioTasksArray (tasks: any) { | 9 | function isValidStudioTasksArray (tasks: any) { |
9 | if (!isArray(tasks)) return false | 10 | if (!isArray(tasks)) return false |
@@ -24,7 +25,7 @@ function isStudioCutTaskValid (task: VideoStudioTask) { | |||
24 | 25 | ||
25 | if (!start || !end) return true | 26 | if (!start || !end) return true |
26 | 27 | ||
27 | return parseInt(start + '') < parseInt(end + '') | 28 | return forceNumber(start) < forceNumber(end) |
28 | } | 29 | } |
29 | 30 | ||
30 | function isStudioTaskAddIntroOutroValid (task: VideoStudioTask, indice: number, files: Express.Multer.File[]) { | 31 | function isStudioTaskAddIntroOutroValid (task: VideoStudioTask, indice: number, files: Express.Multer.File[]) { |
diff --git a/server/helpers/video.ts b/server/helpers/video.ts index f5f645d3e..c688ef1e3 100644 --- a/server/helpers/video.ts +++ b/server/helpers/video.ts | |||
@@ -2,6 +2,7 @@ import { Response } from 'express' | |||
2 | import { CONFIG } from '@server/initializers/config' | 2 | import { CONFIG } from '@server/initializers/config' |
3 | import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models' | 3 | import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models' |
4 | import { VideoPrivacy, VideoState } from '@shared/models' | 4 | import { VideoPrivacy, VideoState } from '@shared/models' |
5 | import { forceNumber } from '@shared/core-utils' | ||
5 | 6 | ||
6 | function getVideoWithAttributes (res: Response) { | 7 | function getVideoWithAttributes (res: Response) { |
7 | return res.locals.videoAPI || res.locals.videoAll || res.locals.onlyVideo | 8 | return res.locals.videoAPI || res.locals.videoAll || res.locals.onlyVideo |
@@ -14,14 +15,14 @@ function extractVideo (videoOrPlaylist: MVideo | MStreamingPlaylistVideo) { | |||
14 | } | 15 | } |
15 | 16 | ||
16 | function isPrivacyForFederation (privacy: VideoPrivacy) { | 17 | function isPrivacyForFederation (privacy: VideoPrivacy) { |
17 | const castedPrivacy = parseInt(privacy + '', 10) | 18 | const castedPrivacy = forceNumber(privacy) |
18 | 19 | ||
19 | return castedPrivacy === VideoPrivacy.PUBLIC || | 20 | return castedPrivacy === VideoPrivacy.PUBLIC || |
20 | (CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true && castedPrivacy === VideoPrivacy.UNLISTED) | 21 | (CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true && castedPrivacy === VideoPrivacy.UNLISTED) |
21 | } | 22 | } |
22 | 23 | ||
23 | function isStateForFederation (state: VideoState) { | 24 | function isStateForFederation (state: VideoState) { |
24 | const castedState = parseInt(state + '', 10) | 25 | const castedState = forceNumber(state) |
25 | 26 | ||
26 | return castedState === VideoState.PUBLISHED || castedState === VideoState.WAITING_FOR_LIVE || castedState === VideoState.LIVE_ENDED | 27 | return castedState === VideoState.PUBLISHED || castedState === VideoState.WAITING_FOR_LIVE || castedState === VideoState.LIVE_ENDED |
27 | } | 28 | } |
diff --git a/server/lib/activitypub/collection.ts b/server/lib/activitypub/collection.ts index f897141ea..a176cab51 100644 --- a/server/lib/activitypub/collection.ts +++ b/server/lib/activitypub/collection.ts | |||
@@ -3,6 +3,7 @@ import validator from 'validator' | |||
3 | import { pageToStartAndCount } from '@server/helpers/core-utils' | 3 | import { pageToStartAndCount } from '@server/helpers/core-utils' |
4 | import { ACTIVITY_PUB } from '@server/initializers/constants' | 4 | import { ACTIVITY_PUB } from '@server/initializers/constants' |
5 | import { ResultList } from '@shared/models' | 5 | import { ResultList } from '@shared/models' |
6 | import { forceNumber } from '@shared/core-utils' | ||
6 | 7 | ||
7 | type ActivityPubCollectionPaginationHandler = (start: number, count: number) => Bluebird<ResultList<any>> | Promise<ResultList<any>> | 8 | type ActivityPubCollectionPaginationHandler = (start: number, count: number) => Bluebird<ResultList<any>> | Promise<ResultList<any>> |
8 | 9 | ||
@@ -33,7 +34,7 @@ async function activityPubCollectionPagination ( | |||
33 | let prev: string | undefined | 34 | let prev: string | undefined |
34 | 35 | ||
35 | // Assert page is a number | 36 | // Assert page is a number |
36 | page = parseInt(page, 10) | 37 | page = forceNumber(page) |
37 | 38 | ||
38 | // There are more results | 39 | // There are more results |
39 | if (result.total > page * size) { | 40 | if (result.total > page * size) { |
diff --git a/server/middlewares/pagination.ts b/server/middlewares/pagination.ts index 9812af9e4..17e43f743 100644 --- a/server/middlewares/pagination.ts +++ b/server/middlewares/pagination.ts | |||
@@ -1,12 +1,13 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { forceNumber } from '@shared/core-utils' | ||
2 | import { PAGINATION } from '../initializers/constants' | 3 | import { PAGINATION } from '../initializers/constants' |
3 | 4 | ||
4 | function setDefaultPagination (req: express.Request, res: express.Response, next: express.NextFunction) { | 5 | function setDefaultPagination (req: express.Request, res: express.Response, next: express.NextFunction) { |
5 | if (!req.query.start) req.query.start = 0 | 6 | if (!req.query.start) req.query.start = 0 |
6 | else req.query.start = parseInt(req.query.start, 10) | 7 | else req.query.start = forceNumber(req.query.start) |
7 | 8 | ||
8 | if (!req.query.count) req.query.count = PAGINATION.GLOBAL.COUNT.DEFAULT | 9 | if (!req.query.count) req.query.count = PAGINATION.GLOBAL.COUNT.DEFAULT |
9 | else req.query.count = parseInt(req.query.count, 10) | 10 | else req.query.count = forceNumber(req.query.count) |
10 | 11 | ||
11 | return next() | 12 | return next() |
12 | } | 13 | } |
diff --git a/server/middlewares/validators/abuse.ts b/server/middlewares/validators/abuse.ts index 9b94008ce..70bae1775 100644 --- a/server/middlewares/validators/abuse.ts +++ b/server/middlewares/validators/abuse.ts | |||
@@ -18,6 +18,7 @@ import { AbuseMessageModel } from '@server/models/abuse/abuse-message' | |||
18 | import { AbuseCreate, UserRight } from '@shared/models' | 18 | import { AbuseCreate, UserRight } from '@shared/models' |
19 | import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' | 19 | import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' |
20 | import { areValidationErrors, doesAbuseExist, doesAccountIdExist, doesCommentIdExist, doesVideoExist } from './shared' | 20 | import { areValidationErrors, doesAbuseExist, doesAccountIdExist, doesCommentIdExist, doesVideoExist } from './shared' |
21 | import { forceNumber } from '@shared/core-utils' | ||
21 | 22 | ||
22 | const abuseReportValidator = [ | 23 | const abuseReportValidator = [ |
23 | body('account.id') | 24 | body('account.id') |
@@ -216,7 +217,7 @@ const deleteAbuseMessageValidator = [ | |||
216 | const user = res.locals.oauth.token.user | 217 | const user = res.locals.oauth.token.user |
217 | const abuse = res.locals.abuse | 218 | const abuse = res.locals.abuse |
218 | 219 | ||
219 | const messageId = parseInt(req.params.messageId + '', 10) | 220 | const messageId = forceNumber(req.params.messageId) |
220 | const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id) | 221 | const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id) |
221 | 222 | ||
222 | if (!abuseMessage) { | 223 | if (!abuseMessage) { |
diff --git a/server/middlewares/validators/redundancy.ts b/server/middlewares/validators/redundancy.ts index 79460f63c..c80f9b728 100644 --- a/server/middlewares/validators/redundancy.ts +++ b/server/middlewares/validators/redundancy.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { body, param, query } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies' | 3 | import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies' |
4 | import { forceNumber } from '@shared/core-utils' | ||
4 | import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' | 5 | import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' |
5 | import { | 6 | import { |
6 | exists, | 7 | exists, |
@@ -171,7 +172,7 @@ const removeVideoRedundancyValidator = [ | |||
171 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 172 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
172 | if (areValidationErrors(req, res)) return | 173 | if (areValidationErrors(req, res)) return |
173 | 174 | ||
174 | const redundancy = await VideoRedundancyModel.loadByIdWithVideo(parseInt(req.params.redundancyId, 10)) | 175 | const redundancy = await VideoRedundancyModel.loadByIdWithVideo(forceNumber(req.params.redundancyId)) |
175 | if (!redundancy) { | 176 | if (!redundancy) { |
176 | return res.fail({ | 177 | return res.fail({ |
177 | status: HttpStatusCode.NOT_FOUND_404, | 178 | status: HttpStatusCode.NOT_FOUND_404, |
diff --git a/server/middlewares/validators/shared/abuses.ts b/server/middlewares/validators/shared/abuses.ts index 2b8d86ba5..2c988f9ec 100644 --- a/server/middlewares/validators/shared/abuses.ts +++ b/server/middlewares/validators/shared/abuses.ts | |||
@@ -1,9 +1,10 @@ | |||
1 | import { Response } from 'express' | 1 | import { Response } from 'express' |
2 | import { AbuseModel } from '@server/models/abuse/abuse' | 2 | import { AbuseModel } from '@server/models/abuse/abuse' |
3 | import { HttpStatusCode } from '@shared/models' | 3 | import { HttpStatusCode } from '@shared/models' |
4 | import { forceNumber } from '@shared/core-utils' | ||
4 | 5 | ||
5 | async function doesAbuseExist (abuseId: number | string, res: Response) { | 6 | async function doesAbuseExist (abuseId: number | string, res: Response) { |
6 | const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) | 7 | const abuse = await AbuseModel.loadByIdWithReporter(forceNumber(abuseId)) |
7 | 8 | ||
8 | if (!abuse) { | 9 | if (!abuse) { |
9 | res.fail({ | 10 | res.fail({ |
diff --git a/server/middlewares/validators/shared/accounts.ts b/server/middlewares/validators/shared/accounts.ts index fe4f83aa0..72b0e235e 100644 --- a/server/middlewares/validators/shared/accounts.ts +++ b/server/middlewares/validators/shared/accounts.ts | |||
@@ -2,10 +2,11 @@ import { Response } from 'express' | |||
2 | import { AccountModel } from '@server/models/account/account' | 2 | import { AccountModel } from '@server/models/account/account' |
3 | import { UserModel } from '@server/models/user/user' | 3 | import { UserModel } from '@server/models/user/user' |
4 | import { MAccountDefault } from '@server/types/models' | 4 | import { MAccountDefault } from '@server/types/models' |
5 | import { forceNumber } from '@shared/core-utils' | ||
5 | import { HttpStatusCode } from '@shared/models' | 6 | import { HttpStatusCode } from '@shared/models' |
6 | 7 | ||
7 | function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) { | 8 | function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) { |
8 | const promise = AccountModel.load(parseInt(id + '', 10)) | 9 | const promise = AccountModel.load(forceNumber(id)) |
9 | 10 | ||
10 | return doesAccountExist(promise, res, sendNotFound) | 11 | return doesAccountExist(promise, res, sendNotFound) |
11 | } | 12 | } |
@@ -40,7 +41,7 @@ async function doesAccountExist (p: Promise<MAccountDefault>, res: Response, sen | |||
40 | } | 41 | } |
41 | 42 | ||
42 | async function doesUserFeedTokenCorrespond (id: number, token: string, res: Response) { | 43 | async function doesUserFeedTokenCorrespond (id: number, token: string, res: Response) { |
43 | const user = await UserModel.loadByIdWithChannels(parseInt(id + '', 10)) | 44 | const user = await UserModel.loadByIdWithChannels(forceNumber(id)) |
44 | 45 | ||
45 | if (token !== user.feedToken) { | 46 | if (token !== user.feedToken) { |
46 | res.fail({ | 47 | res.fail({ |
diff --git a/server/middlewares/validators/shared/users.ts b/server/middlewares/validators/shared/users.ts index fbaa7db0e..b8f1436d3 100644 --- a/server/middlewares/validators/shared/users.ts +++ b/server/middlewares/validators/shared/users.ts | |||
@@ -2,10 +2,11 @@ import express from 'express' | |||
2 | import { ActorModel } from '@server/models/actor/actor' | 2 | import { ActorModel } from '@server/models/actor/actor' |
3 | import { UserModel } from '@server/models/user/user' | 3 | import { UserModel } from '@server/models/user/user' |
4 | import { MUserDefault } from '@server/types/models' | 4 | import { MUserDefault } from '@server/types/models' |
5 | import { forceNumber } from '@shared/core-utils' | ||
5 | import { HttpStatusCode } from '@shared/models' | 6 | import { HttpStatusCode } from '@shared/models' |
6 | 7 | ||
7 | function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) { | 8 | function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) { |
8 | const id = parseInt(idArg + '', 10) | 9 | const id = forceNumber(idArg) |
9 | return checkUserExist(() => UserModel.loadByIdWithChannels(id, withStats), res) | 10 | return checkUserExist(() => UserModel.loadByIdWithChannels(id, withStats), res) |
10 | } | 11 | } |
11 | 12 | ||
diff --git a/server/middlewares/validators/shared/video-comments.ts b/server/middlewares/validators/shared/video-comments.ts index 8d1a16294..0961b3ec9 100644 --- a/server/middlewares/validators/shared/video-comments.ts +++ b/server/middlewares/validators/shared/video-comments.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { VideoCommentModel } from '@server/models/video/video-comment' | 2 | import { VideoCommentModel } from '@server/models/video/video-comment' |
3 | import { MVideoId } from '@server/types/models' | 3 | import { MVideoId } from '@server/types/models' |
4 | import { forceNumber } from '@shared/core-utils' | ||
4 | import { HttpStatusCode, ServerErrorCode } from '@shared/models' | 5 | import { HttpStatusCode, ServerErrorCode } from '@shared/models' |
5 | 6 | ||
6 | async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) { | 7 | async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) { |
7 | const id = parseInt(idArg + '', 10) | 8 | const id = forceNumber(idArg) |
8 | const videoComment = await VideoCommentModel.loadById(id) | 9 | const videoComment = await VideoCommentModel.loadById(id) |
9 | 10 | ||
10 | if (!videoComment) { | 11 | if (!videoComment) { |
@@ -33,7 +34,7 @@ async function doesVideoCommentThreadExist (idArg: number | string, video: MVide | |||
33 | } | 34 | } |
34 | 35 | ||
35 | async function doesVideoCommentExist (idArg: number | string, video: MVideoId, res: express.Response) { | 36 | async function doesVideoCommentExist (idArg: number | string, video: MVideoId, res: express.Response) { |
36 | const id = parseInt(idArg + '', 10) | 37 | const id = forceNumber(idArg) |
37 | const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) | 38 | const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) |
38 | 39 | ||
39 | if (!videoComment) { | 40 | if (!videoComment) { |
@@ -57,7 +58,7 @@ async function doesVideoCommentExist (idArg: number | string, video: MVideoId, r | |||
57 | } | 58 | } |
58 | 59 | ||
59 | async function doesCommentIdExist (idArg: number | string, res: express.Response) { | 60 | async function doesCommentIdExist (idArg: number | string, res: express.Response) { |
60 | const id = parseInt(idArg + '', 10) | 61 | const id = forceNumber(idArg) |
61 | const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) | 62 | const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) |
62 | 63 | ||
63 | if (!videoComment) { | 64 | if (!videoComment) { |
diff --git a/server/middlewares/validators/shared/video-ownerships.ts b/server/middlewares/validators/shared/video-ownerships.ts index 680613cda..33ac9c8b6 100644 --- a/server/middlewares/validators/shared/video-ownerships.ts +++ b/server/middlewares/validators/shared/video-ownerships.ts | |||
@@ -1,9 +1,10 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership' | 2 | import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership' |
3 | import { forceNumber } from '@shared/core-utils' | ||
3 | import { HttpStatusCode } from '@shared/models' | 4 | import { HttpStatusCode } from '@shared/models' |
4 | 5 | ||
5 | async function doesChangeVideoOwnershipExist (idArg: number | string, res: express.Response) { | 6 | async function doesChangeVideoOwnershipExist (idArg: number | string, res: express.Response) { |
6 | const id = parseInt(idArg + '', 10) | 7 | const id = forceNumber(idArg) |
7 | const videoChangeOwnership = await VideoChangeOwnershipModel.load(id) | 8 | const videoChangeOwnership = await VideoChangeOwnershipModel.load(id) |
8 | 9 | ||
9 | if (!videoChangeOwnership) { | 10 | if (!videoChangeOwnership) { |
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 055af3b64..50327b6ae 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { body, param, query } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { Hooks } from '@server/lib/plugins/hooks' | 3 | import { Hooks } from '@server/lib/plugins/hooks' |
4 | import { forceNumber } from '@shared/core-utils' | ||
4 | import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models' | 5 | import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models' |
5 | import { exists, isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' | 6 | import { exists, isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' |
6 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' | 7 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' |
@@ -515,7 +516,7 @@ const usersCheckCurrentPasswordFactory = (targetUserIdGetter: (req: express.Requ | |||
515 | 516 | ||
516 | const user = res.locals.oauth.token.User | 517 | const user = res.locals.oauth.token.User |
517 | const isAdminOrModerator = user.role === UserRole.ADMINISTRATOR || user.role === UserRole.MODERATOR | 518 | const isAdminOrModerator = user.role === UserRole.ADMINISTRATOR || user.role === UserRole.MODERATOR |
518 | const targetUserId = parseInt(targetUserIdGetter(req) + '') | 519 | const targetUserId = forceNumber(targetUserIdGetter(req)) |
519 | 520 | ||
520 | // Admin/moderator action on another user, skip the password check | 521 | // Admin/moderator action on another user, skip the password check |
521 | if (isAdminOrModerator && targetUserId !== user.id) { | 522 | if (isAdminOrModerator && targetUserId !== user.id) { |
diff --git a/server/middlewares/validators/videos/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts index f295b1885..72442aeb6 100644 --- a/server/middlewares/validators/videos/video-imports.ts +++ b/server/middlewares/validators/videos/video-imports.ts | |||
@@ -4,6 +4,7 @@ import { isResolvingToUnicastOnly } from '@server/helpers/dns' | |||
4 | import { isPreImportVideoAccepted } from '@server/lib/moderation' | 4 | import { isPreImportVideoAccepted } from '@server/lib/moderation' |
5 | import { Hooks } from '@server/lib/plugins/hooks' | 5 | import { Hooks } from '@server/lib/plugins/hooks' |
6 | import { MUserAccountId, MVideoImport } from '@server/types/models' | 6 | import { MUserAccountId, MVideoImport } from '@server/types/models' |
7 | import { forceNumber } from '@shared/core-utils' | ||
7 | import { HttpStatusCode, UserRight, VideoImportState } from '@shared/models' | 8 | import { HttpStatusCode, UserRight, VideoImportState } from '@shared/models' |
8 | import { VideoImportCreate } from '@shared/models/videos/import/video-import-create.model' | 9 | import { VideoImportCreate } from '@shared/models/videos/import/video-import-create.model' |
9 | import { isIdValid, toIntOrNull } from '../../../helpers/custom-validators/misc' | 10 | import { isIdValid, toIntOrNull } from '../../../helpers/custom-validators/misc' |
@@ -130,7 +131,7 @@ const videoImportCancelValidator = [ | |||
130 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 131 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
131 | if (areValidationErrors(req, res)) return | 132 | if (areValidationErrors(req, res)) return |
132 | 133 | ||
133 | if (!await doesVideoImportExist(parseInt(req.params.id), res)) return | 134 | if (!await doesVideoImportExist(forceNumber(req.params.id), res)) return |
134 | if (!checkUserCanManageImport(res.locals.oauth.token.user, res.locals.videoImport, res)) return | 135 | if (!checkUserCanManageImport(res.locals.oauth.token.user, res.locals.videoImport, res)) return |
135 | 136 | ||
136 | if (res.locals.videoImport.state !== VideoImportState.PENDING) { | 137 | if (res.locals.videoImport.state !== VideoImportState.PENDING) { |
diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts index 6d4b8a6f1..e4b7e5c56 100644 --- a/server/middlewares/validators/videos/video-playlists.ts +++ b/server/middlewares/validators/videos/video-playlists.ts | |||
@@ -2,6 +2,7 @@ import express from 'express' | |||
2 | import { body, param, query, ValidationChain } from 'express-validator' | 2 | import { body, param, query, ValidationChain } from 'express-validator' |
3 | import { ExpressPromiseHandler } from '@server/types/express-handler' | 3 | import { ExpressPromiseHandler } from '@server/types/express-handler' |
4 | import { MUserAccountId } from '@server/types/models' | 4 | import { MUserAccountId } from '@server/types/models' |
5 | import { forceNumber } from '@shared/core-utils' | ||
5 | import { | 6 | import { |
6 | HttpStatusCode, | 7 | HttpStatusCode, |
7 | UserRight, | 8 | UserRight, |
@@ -258,7 +259,7 @@ const videoPlaylistElementAPGetValidator = [ | |||
258 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 259 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
259 | if (areValidationErrors(req, res)) return | 260 | if (areValidationErrors(req, res)) return |
260 | 261 | ||
261 | const playlistElementId = parseInt(req.params.playlistElementId + '', 10) | 262 | const playlistElementId = forceNumber(req.params.playlistElementId) |
262 | const playlistId = req.params.playlistId | 263 | const playlistId = req.params.playlistId |
263 | 264 | ||
264 | const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId) | 265 | const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId) |
diff --git a/server/models/abuse/abuse-query-builder.ts b/server/models/abuse/abuse-query-builder.ts index cfc924ba4..74f4542e5 100644 --- a/server/models/abuse/abuse-query-builder.ts +++ b/server/models/abuse/abuse-query-builder.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | 1 | ||
2 | import { exists } from '@server/helpers/custom-validators/misc' | 2 | import { exists } from '@server/helpers/custom-validators/misc' |
3 | import { forceNumber } from '@shared/core-utils' | ||
3 | import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models' | 4 | import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models' |
4 | import { buildBlockedAccountSQL, buildDirectionAndField } from '../utils' | 5 | import { buildBlockedAccountSQL, buildDirectionAndField } from '../utils' |
5 | 6 | ||
@@ -135,12 +136,12 @@ function buildAbuseListQuery (options: BuildAbusesQueryOptions, type: 'count' | | |||
135 | } | 136 | } |
136 | 137 | ||
137 | if (exists(options.count)) { | 138 | if (exists(options.count)) { |
138 | const count = parseInt(options.count + '', 10) | 139 | const count = forceNumber(options.count) |
139 | suffix += `LIMIT ${count} ` | 140 | suffix += `LIMIT ${count} ` |
140 | } | 141 | } |
141 | 142 | ||
142 | if (exists(options.start)) { | 143 | if (exists(options.start)) { |
143 | const start = parseInt(options.start + '', 10) | 144 | const start = forceNumber(options.start) |
144 | suffix += `OFFSET ${start} ` | 145 | suffix += `OFFSET ${start} ` |
145 | } | 146 | } |
146 | } | 147 | } |
diff --git a/server/models/actor/actor.ts b/server/models/actor/actor.ts index 88db241dc..d7afa727d 100644 --- a/server/models/actor/actor.ts +++ b/server/models/actor/actor.ts | |||
@@ -18,7 +18,7 @@ import { | |||
18 | import { activityPubContextify } from '@server/lib/activitypub/context' | 18 | import { activityPubContextify } from '@server/lib/activitypub/context' |
19 | import { getBiggestActorImage } from '@server/lib/actor-image' | 19 | import { getBiggestActorImage } from '@server/lib/actor-image' |
20 | import { ModelCache } from '@server/models/model-cache' | 20 | import { ModelCache } from '@server/models/model-cache' |
21 | import { getLowercaseExtension } from '@shared/core-utils' | 21 | import { forceNumber, getLowercaseExtension } from '@shared/core-utils' |
22 | import { ActivityIconObject, ActivityPubActorType, ActorImageType } from '@shared/models' | 22 | import { ActivityIconObject, ActivityPubActorType, ActorImageType } from '@shared/models' |
23 | import { AttributesOnly } from '@shared/typescript-utils' | 23 | import { AttributesOnly } from '@shared/typescript-utils' |
24 | import { | 24 | import { |
@@ -446,7 +446,7 @@ export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> { | |||
446 | } | 446 | } |
447 | 447 | ||
448 | static rebuildFollowsCount (ofId: number, type: 'followers' | 'following', transaction?: Transaction) { | 448 | static rebuildFollowsCount (ofId: number, type: 'followers' | 'following', transaction?: Transaction) { |
449 | const sanitizedOfId = parseInt(ofId + '', 10) | 449 | const sanitizedOfId = forceNumber(ofId) |
450 | const where = { id: sanitizedOfId } | 450 | const where = { id: sanitizedOfId } |
451 | 451 | ||
452 | let columnToUpdate: string | 452 | let columnToUpdate: string |
diff --git a/server/models/user/user-notification.ts b/server/models/user/user-notification.ts index 6209cb4bf..d37fa5dc7 100644 --- a/server/models/user/user-notification.ts +++ b/server/models/user/user-notification.ts | |||
@@ -2,6 +2,7 @@ import { ModelIndexesOptions, Op, WhereOptions } from 'sequelize' | |||
2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { getBiggestActorImage } from '@server/lib/actor-image' | 3 | import { getBiggestActorImage } from '@server/lib/actor-image' |
4 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' | 4 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' |
5 | import { forceNumber } from '@shared/core-utils' | ||
5 | import { uuidToShort } from '@shared/extra-utils' | 6 | import { uuidToShort } from '@shared/extra-utils' |
6 | import { UserNotification, UserNotificationType } from '@shared/models' | 7 | import { UserNotification, UserNotificationType } from '@shared/models' |
7 | import { AttributesOnly } from '@shared/typescript-utils' | 8 | import { AttributesOnly } from '@shared/typescript-utils' |
@@ -284,7 +285,7 @@ export class UserNotificationModel extends Model<Partial<AttributesOnly<UserNoti | |||
284 | } | 285 | } |
285 | 286 | ||
286 | static removeNotificationsOf (options: { id: number, type: 'account' | 'server', forUserId?: number }) { | 287 | static removeNotificationsOf (options: { id: number, type: 'account' | 'server', forUserId?: number }) { |
287 | const id = parseInt(options.id + '', 10) | 288 | const id = forceNumber(options.id) |
288 | 289 | ||
289 | function buildAccountWhereQuery (base: string) { | 290 | function buildAccountWhereQuery (base: string) { |
290 | const whereSuffix = options.forUserId | 291 | const whereSuffix = options.forUserId |
diff --git a/server/models/user/user.ts b/server/models/user/user.ts index f70feed73..672728a2a 100644 --- a/server/models/user/user.ts +++ b/server/models/user/user.ts | |||
@@ -70,6 +70,7 @@ import { VideoImportModel } from '../video/video-import' | |||
70 | import { VideoLiveModel } from '../video/video-live' | 70 | import { VideoLiveModel } from '../video/video-live' |
71 | import { VideoPlaylistModel } from '../video/video-playlist' | 71 | import { VideoPlaylistModel } from '../video/video-playlist' |
72 | import { UserNotificationSettingModel } from './user-notification-setting' | 72 | import { UserNotificationSettingModel } from './user-notification-setting' |
73 | import { forceNumber } from '@shared/core-utils' | ||
73 | 74 | ||
74 | enum ScopeNames { | 75 | enum ScopeNames { |
75 | FOR_ME_API = 'FOR_ME_API', | 76 | FOR_ME_API = 'FOR_ME_API', |
@@ -900,27 +901,27 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> { | |||
900 | videoQuotaDaily: this.videoQuotaDaily, | 901 | videoQuotaDaily: this.videoQuotaDaily, |
901 | 902 | ||
902 | videoQuotaUsed: videoQuotaUsed !== undefined | 903 | videoQuotaUsed: videoQuotaUsed !== undefined |
903 | ? parseInt(videoQuotaUsed + '', 10) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id) | 904 | ? forceNumber(videoQuotaUsed) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id) |
904 | : undefined, | 905 | : undefined, |
905 | 906 | ||
906 | videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined | 907 | videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined |
907 | ? parseInt(videoQuotaUsedDaily + '', 10) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id) | 908 | ? forceNumber(videoQuotaUsedDaily) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id) |
908 | : undefined, | 909 | : undefined, |
909 | 910 | ||
910 | videosCount: videosCount !== undefined | 911 | videosCount: videosCount !== undefined |
911 | ? parseInt(videosCount + '', 10) | 912 | ? forceNumber(videosCount) |
912 | : undefined, | 913 | : undefined, |
913 | abusesCount: abusesCount | 914 | abusesCount: abusesCount |
914 | ? parseInt(abusesCount, 10) | 915 | ? forceNumber(abusesCount) |
915 | : undefined, | 916 | : undefined, |
916 | abusesAcceptedCount: abusesAcceptedCount | 917 | abusesAcceptedCount: abusesAcceptedCount |
917 | ? parseInt(abusesAcceptedCount, 10) | 918 | ? forceNumber(abusesAcceptedCount) |
918 | : undefined, | 919 | : undefined, |
919 | abusesCreatedCount: abusesCreatedCount !== undefined | 920 | abusesCreatedCount: abusesCreatedCount !== undefined |
920 | ? parseInt(abusesCreatedCount + '', 10) | 921 | ? forceNumber(abusesCreatedCount) |
921 | : undefined, | 922 | : undefined, |
922 | videoCommentsCount: videoCommentsCount !== undefined | 923 | videoCommentsCount: videoCommentsCount !== undefined |
923 | ? parseInt(videoCommentsCount + '', 10) | 924 | ? forceNumber(videoCommentsCount) |
924 | : undefined, | 925 | : undefined, |
925 | 926 | ||
926 | noInstanceConfigWarningModal: this.noInstanceConfigWarningModal, | 927 | noInstanceConfigWarningModal: this.noInstanceConfigWarningModal, |
diff --git a/server/models/utils.ts b/server/models/utils.ts index 1e168d419..3476799ce 100644 --- a/server/models/utils.ts +++ b/server/models/utils.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { literal, Op, OrderItem, Sequelize } from 'sequelize' | 1 | import { literal, Op, OrderItem, Sequelize } from 'sequelize' |
2 | import validator from 'validator' | 2 | import validator from 'validator' |
3 | import { forceNumber } from '@shared/core-utils' | ||
3 | 4 | ||
4 | type SortType = { sortModel: string, sortValue: string } | 5 | type SortType = { sortModel: string, sortValue: string } |
5 | 6 | ||
@@ -202,7 +203,7 @@ function buildBlockedAccountSQLOptimized (columnNameJoin: string, blockerIds: nu | |||
202 | } | 203 | } |
203 | 204 | ||
204 | function buildServerIdsFollowedBy (actorId: any) { | 205 | function buildServerIdsFollowedBy (actorId: any) { |
205 | const actorIdNumber = parseInt(actorId + '', 10) | 206 | const actorIdNumber = forceNumber(actorId) |
206 | 207 | ||
207 | return '(' + | 208 | return '(' + |
208 | 'SELECT "actor"."serverId" FROM "actorFollow" ' + | 209 | 'SELECT "actor"."serverId" FROM "actorFollow" ' + |
@@ -218,7 +219,7 @@ function buildWhereIdOrUUID (id: number | string) { | |||
218 | function parseAggregateResult (result: any) { | 219 | function parseAggregateResult (result: any) { |
219 | if (!result) return 0 | 220 | if (!result) return 0 |
220 | 221 | ||
221 | const total = parseInt(result + '', 10) | 222 | const total = forceNumber(result) |
222 | if (isNaN(total)) return 0 | 223 | if (isNaN(total)) return 0 |
223 | 224 | ||
224 | return total | 225 | return total |
diff --git a/server/models/video/sql/video/videos-id-list-query-builder.ts b/server/models/video/sql/video/videos-id-list-query-builder.ts index 14f903851..7c864bf27 100644 --- a/server/models/video/sql/video/videos-id-list-query-builder.ts +++ b/server/models/video/sql/video/videos-id-list-query-builder.ts | |||
@@ -6,6 +6,7 @@ import { buildDirectionAndField, createSafeIn, parseRowCountResult } from '@serv | |||
6 | import { MUserAccountId, MUserId } from '@server/types/models' | 6 | import { MUserAccountId, MUserId } from '@server/types/models' |
7 | import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models' | 7 | import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models' |
8 | import { AbstractRunQuery } from '../../../shared/abstract-run-query' | 8 | import { AbstractRunQuery } from '../../../shared/abstract-run-query' |
9 | import { forceNumber } from '@shared/core-utils' | ||
9 | 10 | ||
10 | /** | 11 | /** |
11 | * | 12 | * |
@@ -689,12 +690,12 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery { | |||
689 | } | 690 | } |
690 | 691 | ||
691 | private setLimit (countArg: number) { | 692 | private setLimit (countArg: number) { |
692 | const count = parseInt(countArg + '', 10) | 693 | const count = forceNumber(countArg) |
693 | this.limit = `LIMIT ${count}` | 694 | this.limit = `LIMIT ${count}` |
694 | } | 695 | } |
695 | 696 | ||
696 | private setOffset (startArg: number) { | 697 | private setOffset (startArg: number) { |
697 | const start = parseInt(startArg + '', 10) | 698 | const start = forceNumber(startArg) |
698 | this.offset = `OFFSET ${start}` | 699 | this.offset = `OFFSET ${start}` |
699 | } | 700 | } |
700 | } | 701 | } |
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 91dafbcf1..9e461b6ca 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -19,7 +19,7 @@ import { | |||
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { CONFIG } from '@server/initializers/config' | 20 | import { CONFIG } from '@server/initializers/config' |
21 | import { MAccountActor } from '@server/types/models' | 21 | import { MAccountActor } from '@server/types/models' |
22 | import { pick } from '@shared/core-utils' | 22 | import { forceNumber, pick } from '@shared/core-utils' |
23 | import { AttributesOnly } from '@shared/typescript-utils' | 23 | import { AttributesOnly } from '@shared/typescript-utils' |
24 | import { ActivityPubActor } from '../../../shared/models/activitypub' | 24 | import { ActivityPubActor } from '../../../shared/models/activitypub' |
25 | import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' | 25 | import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' |
@@ -280,7 +280,7 @@ export type SummaryOptions = { | |||
280 | ] | 280 | ] |
281 | }, | 281 | }, |
282 | [ScopeNames.WITH_STATS]: (options: AvailableWithStatsOptions = { daysPrior: 30 }) => { | 282 | [ScopeNames.WITH_STATS]: (options: AvailableWithStatsOptions = { daysPrior: 30 }) => { |
283 | const daysPrior = parseInt(options.daysPrior + '', 10) | 283 | const daysPrior = forceNumber(options.daysPrior) |
284 | 284 | ||
285 | return { | 285 | return { |
286 | attributes: { | 286 | attributes: { |
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts index b45f15bd6..7181b5599 100644 --- a/server/models/video/video-playlist-element.ts +++ b/server/models/video/video-playlist-element.ts | |||
@@ -23,6 +23,7 @@ import { | |||
23 | MVideoPlaylistElementVideoUrlPlaylistPrivacy, | 23 | MVideoPlaylistElementVideoUrlPlaylistPrivacy, |
24 | MVideoPlaylistVideoThumbnail | 24 | MVideoPlaylistVideoThumbnail |
25 | } from '@server/types/models/video/video-playlist-element' | 25 | } from '@server/types/models/video/video-playlist-element' |
26 | import { forceNumber } from '@shared/core-utils' | ||
26 | import { AttributesOnly } from '@shared/typescript-utils' | 27 | import { AttributesOnly } from '@shared/typescript-utils' |
27 | import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object' | 28 | import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object' |
28 | import { VideoPrivacy } from '../../../shared/models/videos' | 29 | import { VideoPrivacy } from '../../../shared/models/videos' |
@@ -185,7 +186,9 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide | |||
185 | playlistId: number | string, | 186 | playlistId: number | string, |
186 | playlistElementId: number | 187 | playlistElementId: number |
187 | ): Promise<MVideoPlaylistElementVideoUrlPlaylistPrivacy> { | 188 | ): Promise<MVideoPlaylistElementVideoUrlPlaylistPrivacy> { |
188 | const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId } | 189 | const playlistWhere = validator.isUUID('' + playlistId) |
190 | ? { uuid: playlistId } | ||
191 | : { id: playlistId } | ||
189 | 192 | ||
190 | const query = { | 193 | const query = { |
191 | include: [ | 194 | include: [ |
@@ -262,13 +265,15 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide | |||
262 | .then(position => position ? position + 1 : 1) | 265 | .then(position => position ? position + 1 : 1) |
263 | } | 266 | } |
264 | 267 | ||
265 | static reassignPositionOf ( | 268 | static reassignPositionOf (options: { |
266 | videoPlaylistId: number, | 269 | videoPlaylistId: number |
267 | firstPosition: number, | 270 | firstPosition: number |
268 | endPosition: number, | 271 | endPosition: number |
269 | newPosition: number, | 272 | newPosition: number |
270 | transaction?: Transaction | 273 | transaction?: Transaction |
271 | ) { | 274 | }) { |
275 | const { videoPlaylistId, firstPosition, endPosition, newPosition, transaction } = options | ||
276 | |||
272 | const query = { | 277 | const query = { |
273 | where: { | 278 | where: { |
274 | videoPlaylistId, | 279 | videoPlaylistId, |
@@ -281,7 +286,7 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide | |||
281 | validate: false // We use a literal to update the position | 286 | validate: false // We use a literal to update the position |
282 | } | 287 | } |
283 | 288 | ||
284 | const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) | 289 | const positionQuery = Sequelize.literal(`${forceNumber(newPosition)} + "position" - ${forceNumber(firstPosition)}`) |
285 | return VideoPlaylistElementModel.update({ position: positionQuery }, query) | 290 | return VideoPlaylistElementModel.update({ position: positionQuery }, query) |
286 | } | 291 | } |
287 | 292 | ||
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts index ca63bb2d9..f2190037e 100644 --- a/server/models/video/video-share.ts +++ b/server/models/video/video-share.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { literal, Op, QueryTypes, Transaction } from 'sequelize' | 1 | import { literal, Op, QueryTypes, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { forceNumber } from '@shared/core-utils' | ||
3 | import { AttributesOnly } from '@shared/typescript-utils' | 4 | import { AttributesOnly } from '@shared/typescript-utils' |
4 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 5 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
5 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 6 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
@@ -123,7 +124,7 @@ export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareMode | |||
123 | } | 124 | } |
124 | 125 | ||
125 | static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Promise<MActorDefault[]> { | 126 | static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Promise<MActorDefault[]> { |
126 | const safeOwnerId = parseInt(actorOwnerId + '', 10) | 127 | const safeOwnerId = forceNumber(actorOwnerId) |
127 | 128 | ||
128 | // /!\ On actor model | 129 | // /!\ On actor model |
129 | const query = { | 130 | const query = { |
@@ -148,7 +149,7 @@ export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareMode | |||
148 | } | 149 | } |
149 | 150 | ||
150 | static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Promise<MActorDefault[]> { | 151 | static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Promise<MActorDefault[]> { |
151 | const safeChannelId = parseInt(videoChannelId + '', 10) | 152 | const safeChannelId = forceNumber(videoChannelId) |
152 | 153 | ||
153 | // /!\ On actor model | 154 | // /!\ On actor model |
154 | const query = { | 155 | const query = { |
diff --git a/server/tools/peertube-redundancy.ts b/server/tools/peertube-redundancy.ts index 4bb9fbc5a..5c82fa420 100644 --- a/server/tools/peertube-redundancy.ts +++ b/server/tools/peertube-redundancy.ts | |||
@@ -2,7 +2,7 @@ import CliTable3 from 'cli-table3' | |||
2 | import { Command, program } from 'commander' | 2 | import { Command, program } from 'commander' |
3 | import { URL } from 'url' | 3 | import { URL } from 'url' |
4 | import validator from 'validator' | 4 | import validator from 'validator' |
5 | import { uniqify } from '@shared/core-utils' | 5 | import { forceNumber, uniqify } from '@shared/core-utils' |
6 | import { HttpStatusCode, VideoRedundanciesTarget } from '@shared/models' | 6 | import { HttpStatusCode, VideoRedundanciesTarget } from '@shared/models' |
7 | import { assignToken, buildServer, getServerCredentials } from './cli' | 7 | import { assignToken, buildServer, getServerCredentials } from './cli' |
8 | 8 | ||
@@ -138,7 +138,7 @@ async function removeRedundancyCLI (options: { video: number }, command: Command | |||
138 | process.exit(-1) | 138 | process.exit(-1) |
139 | } | 139 | } |
140 | 140 | ||
141 | const videoId = parseInt(options.video + '', 10) | 141 | const videoId = forceNumber(options.video) |
142 | 142 | ||
143 | const myVideoRedundancies = await server.redundancy.listVideos({ target: 'my-videos' }) | 143 | const myVideoRedundancies = await server.redundancy.listVideos({ target: 'my-videos' }) |
144 | let videoRedundancy = myVideoRedundancies.data.find(r => videoId === r.id) | 144 | let videoRedundancy = myVideoRedundancies.data.find(r => videoId === r.id) |