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/models/video | |
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/models/video')
-rw-r--r-- | server/models/video/sql/video/videos-id-list-query-builder.ts | 5 | ||||
-rw-r--r-- | server/models/video/video-channel.ts | 4 | ||||
-rw-r--r-- | server/models/video/video-playlist-element.ts | 21 | ||||
-rw-r--r-- | server/models/video/video-share.ts | 5 |
4 files changed, 21 insertions, 14 deletions
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 = { |