aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-11-15 14:41:55 +0100
committerChocobozzz <me@florianbigard.com>2022-11-15 14:41:55 +0100
commit4638cd713dcdd007cd7f49b9a95fa62ac7823e7c (patch)
tree3e341c6ebbd1ce9e2bbacd72e7e3793e0bd467c2 /server/models
parent6bcb559fc9a491fc3ce83e7c077ee9dc742b1d63 (diff)
downloadPeerTube-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')
-rw-r--r--server/models/abuse/abuse-query-builder.ts5
-rw-r--r--server/models/actor/actor.ts4
-rw-r--r--server/models/user/user-notification.ts3
-rw-r--r--server/models/user/user.ts15
-rw-r--r--server/models/utils.ts5
-rw-r--r--server/models/video/sql/video/videos-id-list-query-builder.ts5
-rw-r--r--server/models/video/video-channel.ts4
-rw-r--r--server/models/video/video-playlist-element.ts21
-rw-r--r--server/models/video/video-share.ts5
9 files changed, 39 insertions, 28 deletions
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
2import { exists } from '@server/helpers/custom-validators/misc' 2import { exists } from '@server/helpers/custom-validators/misc'
3import { forceNumber } from '@shared/core-utils'
3import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models' 4import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models'
4import { buildBlockedAccountSQL, buildDirectionAndField } from '../utils' 5import { 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 {
18import { activityPubContextify } from '@server/lib/activitypub/context' 18import { activityPubContextify } from '@server/lib/activitypub/context'
19import { getBiggestActorImage } from '@server/lib/actor-image' 19import { getBiggestActorImage } from '@server/lib/actor-image'
20import { ModelCache } from '@server/models/model-cache' 20import { ModelCache } from '@server/models/model-cache'
21import { getLowercaseExtension } from '@shared/core-utils' 21import { forceNumber, getLowercaseExtension } from '@shared/core-utils'
22import { ActivityIconObject, ActivityPubActorType, ActorImageType } from '@shared/models' 22import { ActivityIconObject, ActivityPubActorType, ActorImageType } from '@shared/models'
23import { AttributesOnly } from '@shared/typescript-utils' 23import { AttributesOnly } from '@shared/typescript-utils'
24import { 24import {
@@ -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'
2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { getBiggestActorImage } from '@server/lib/actor-image' 3import { getBiggestActorImage } from '@server/lib/actor-image'
4import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' 4import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user'
5import { forceNumber } from '@shared/core-utils'
5import { uuidToShort } from '@shared/extra-utils' 6import { uuidToShort } from '@shared/extra-utils'
6import { UserNotification, UserNotificationType } from '@shared/models' 7import { UserNotification, UserNotificationType } from '@shared/models'
7import { AttributesOnly } from '@shared/typescript-utils' 8import { 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'
70import { VideoLiveModel } from '../video/video-live' 70import { VideoLiveModel } from '../video/video-live'
71import { VideoPlaylistModel } from '../video/video-playlist' 71import { VideoPlaylistModel } from '../video/video-playlist'
72import { UserNotificationSettingModel } from './user-notification-setting' 72import { UserNotificationSettingModel } from './user-notification-setting'
73import { forceNumber } from '@shared/core-utils'
73 74
74enum ScopeNames { 75enum 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 @@
1import { literal, Op, OrderItem, Sequelize } from 'sequelize' 1import { literal, Op, OrderItem, Sequelize } from 'sequelize'
2import validator from 'validator' 2import validator from 'validator'
3import { forceNumber } from '@shared/core-utils'
3 4
4type SortType = { sortModel: string, sortValue: string } 5type SortType = { sortModel: string, sortValue: string }
5 6
@@ -202,7 +203,7 @@ function buildBlockedAccountSQLOptimized (columnNameJoin: string, blockerIds: nu
202} 203}
203 204
204function buildServerIdsFollowedBy (actorId: any) { 205function 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) {
218function parseAggregateResult (result: any) { 219function 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
6import { MUserAccountId, MUserId } from '@server/types/models' 6import { MUserAccountId, MUserId } from '@server/types/models'
7import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models' 7import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models'
8import { AbstractRunQuery } from '../../../shared/abstract-run-query' 8import { AbstractRunQuery } from '../../../shared/abstract-run-query'
9import { 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'
20import { CONFIG } from '@server/initializers/config' 20import { CONFIG } from '@server/initializers/config'
21import { MAccountActor } from '@server/types/models' 21import { MAccountActor } from '@server/types/models'
22import { pick } from '@shared/core-utils' 22import { forceNumber, pick } from '@shared/core-utils'
23import { AttributesOnly } from '@shared/typescript-utils' 23import { AttributesOnly } from '@shared/typescript-utils'
24import { ActivityPubActor } from '../../../shared/models/activitypub' 24import { ActivityPubActor } from '../../../shared/models/activitypub'
25import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' 25import { 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'
26import { forceNumber } from '@shared/core-utils'
26import { AttributesOnly } from '@shared/typescript-utils' 27import { AttributesOnly } from '@shared/typescript-utils'
27import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object' 28import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
28import { VideoPrivacy } from '../../../shared/models/videos' 29import { 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 @@
1import { literal, Op, QueryTypes, Transaction } from 'sequelize' 1import { literal, Op, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
3import { forceNumber } from '@shared/core-utils'
3import { AttributesOnly } from '@shared/typescript-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
4import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 5import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
5import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 6import { 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 = {