Don't inject untrusted input
Even if it's already checked in middlewares It's better to have safe modals too
This commit is contained in:
parent
6bcb559fc9
commit
4638cd713d
35 changed files with 101 additions and 63 deletions
|
@ -105,8 +105,6 @@ export class ManagerOptionsBuilder {
|
|||
Object.assign(videojsOptions, { language: commonOptions.language })
|
||||
}
|
||||
|
||||
console.log(videojsOptions)
|
||||
|
||||
return videojsOptions
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { forceNumber } from '@shared/core-utils'
|
||||
import express from 'express'
|
||||
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
|
||||
import { getFormattedObjects } from '../../../helpers/utils'
|
||||
|
@ -55,7 +56,7 @@ async function listMyVideosHistory (req: express.Request, res: express.Response)
|
|||
async function removeUserHistoryElement (req: express.Request, res: express.Response) {
|
||||
const user = res.locals.oauth.token.User
|
||||
|
||||
await UserVideoHistoryModel.removeUserHistoryElement(user, parseInt(req.params.videoId + ''))
|
||||
await UserVideoHistoryModel.removeUserHistoryElement(user, forceNumber(req.params.videoId))
|
||||
|
||||
return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { uuidToShort } from '@shared/extra-utils'
|
||||
import express from 'express'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { uuidToShort } from '@shared/extra-utils'
|
||||
import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
|
||||
import { asyncMiddleware, authenticate } from '../../../middlewares'
|
||||
import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists'
|
||||
|
@ -22,7 +23,7 @@ export {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function doVideosInPlaylistExist (req: express.Request, res: express.Response) {
|
||||
const videoIds = req.query.videoIds.map(i => parseInt(i + '', 10))
|
||||
const videoIds = req.query.videoIds.map(i => forceNumber(i))
|
||||
const user = res.locals.oauth.token.User
|
||||
|
||||
const results = await VideoPlaylistModel.listPlaylistSummariesOf(user.Account.id, videoIds)
|
||||
|
|
|
@ -46,6 +46,7 @@ import {
|
|||
import { AccountModel } from '../../models/account/account'
|
||||
import { VideoPlaylistModel } from '../../models/video/video-playlist'
|
||||
import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT)
|
||||
|
||||
|
@ -245,7 +246,7 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response)
|
|||
if (videoPlaylistInfoToUpdate.description !== undefined) videoPlaylistInstance.description = videoPlaylistInfoToUpdate.description
|
||||
|
||||
if (videoPlaylistInfoToUpdate.privacy !== undefined) {
|
||||
videoPlaylistInstance.privacy = parseInt(videoPlaylistInfoToUpdate.privacy.toString(), 10)
|
||||
videoPlaylistInstance.privacy = forceNumber(videoPlaylistInfoToUpdate.privacy)
|
||||
|
||||
if (wasNotPrivatePlaylist === true && videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE) {
|
||||
await sendDeleteVideoPlaylist(videoPlaylistInstance, t)
|
||||
|
@ -424,7 +425,7 @@ async function reorderVideosPlaylist (req: express.Request, res: express.Respons
|
|||
|
||||
const endOldPosition = oldPosition + reorderLength - 1
|
||||
// Insert our reordered elements in their place (update)
|
||||
await VideoPlaylistElementModel.reassignPositionOf(videoPlaylist.id, oldPosition, endOldPosition, newPosition, t)
|
||||
await VideoPlaylistElementModel.reassignPositionOf({ videoPlaylistId: videoPlaylist.id, firstPosition: oldPosition, endPosition: endOldPosition, newPosition, transaction: t })
|
||||
|
||||
// Decrease positions of elements after the old position of our ordered elements (decrease)
|
||||
await VideoPlaylistElementModel.increasePositionOf(videoPlaylist.id, oldPosition, -reorderLength, t)
|
||||
|
|
|
@ -19,6 +19,7 @@ import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosU
|
|||
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
|
||||
import { VideoModel } from '../../../models/video/video'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
const lTags = loggerTagsFactory('api', 'video')
|
||||
const auditLogger = auditLoggerFactory('videos')
|
||||
|
@ -174,7 +175,7 @@ async function updateVideoPrivacy (options: {
|
|||
const { videoInstance, videoInfoToUpdate, hadPrivacyForFederation, transaction } = options
|
||||
const isNewVideo = videoInstance.isNewVideo(videoInfoToUpdate.privacy)
|
||||
|
||||
const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10)
|
||||
const newPrivacy = forceNumber(videoInfoToUpdate.privacy)
|
||||
setVideoPrivacy(videoInstance, newPrivacy)
|
||||
|
||||
// Unfederate the video if the new privacy is not compatible with federation
|
||||
|
|
|
@ -5,7 +5,7 @@ import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache
|
|||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
|
||||
import { addQueryParams } from '@shared/core-utils'
|
||||
import { addQueryParams, forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models'
|
||||
import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
|
||||
import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares'
|
||||
|
@ -132,7 +132,7 @@ async function downloadHLSVideoFile (req: express.Request, res: express.Response
|
|||
}
|
||||
|
||||
function getVideoFile (req: express.Request, files: MVideoFile[]) {
|
||||
const resolution = parseInt(req.params.resolution, 10)
|
||||
const resolution = forceNumber(req.params.resolution)
|
||||
return files.find(f => f.resolution === resolution)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { escapeHTML } from '@shared/core-utils/renderer'
|
|||
import { EMBED_SIZE, PREVIEWS_SIZE, THUMBNAILS_SIZE, WEBSERVER } from '../initializers/constants'
|
||||
import { asyncMiddleware, oembedValidator } from '../middlewares'
|
||||
import { accountNameWithHostGetValidator } from '../middlewares/validators'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
const servicesRouter = express.Router()
|
||||
|
||||
|
@ -108,8 +109,8 @@ function buildOEmbed (options: {
|
|||
const { req, previewSize, previewPath, title, channel, embedPath } = options
|
||||
|
||||
const webserverUrl = WEBSERVER.URL
|
||||
const maxHeight = parseInt(req.query.maxheight, 10)
|
||||
const maxWidth = parseInt(req.query.maxwidth, 10)
|
||||
const maxHeight = forceNumber(req.query.maxheight)
|
||||
const maxWidth = forceNumber(req.query.maxwidth)
|
||||
|
||||
const embedUrl = webserverUrl + embedPath
|
||||
const embedTitle = escapeHTML(title)
|
||||
|
|
|
@ -4,6 +4,7 @@ import { buildTaskFileFieldname } from '@server/lib/video-studio'
|
|||
import { VideoStudioTask } from '@shared/models'
|
||||
import { isArray } from './misc'
|
||||
import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
function isValidStudioTasksArray (tasks: any) {
|
||||
if (!isArray(tasks)) return false
|
||||
|
@ -24,7 +25,7 @@ function isStudioCutTaskValid (task: VideoStudioTask) {
|
|||
|
||||
if (!start || !end) return true
|
||||
|
||||
return parseInt(start + '') < parseInt(end + '')
|
||||
return forceNumber(start) < forceNumber(end)
|
||||
}
|
||||
|
||||
function isStudioTaskAddIntroOutroValid (task: VideoStudioTask, indice: number, files: Express.Multer.File[]) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Response } from 'express'
|
|||
import { CONFIG } from '@server/initializers/config'
|
||||
import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models'
|
||||
import { VideoPrivacy, VideoState } from '@shared/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
function getVideoWithAttributes (res: Response) {
|
||||
return res.locals.videoAPI || res.locals.videoAll || res.locals.onlyVideo
|
||||
|
@ -14,14 +15,14 @@ function extractVideo (videoOrPlaylist: MVideo | MStreamingPlaylistVideo) {
|
|||
}
|
||||
|
||||
function isPrivacyForFederation (privacy: VideoPrivacy) {
|
||||
const castedPrivacy = parseInt(privacy + '', 10)
|
||||
const castedPrivacy = forceNumber(privacy)
|
||||
|
||||
return castedPrivacy === VideoPrivacy.PUBLIC ||
|
||||
(CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true && castedPrivacy === VideoPrivacy.UNLISTED)
|
||||
}
|
||||
|
||||
function isStateForFederation (state: VideoState) {
|
||||
const castedState = parseInt(state + '', 10)
|
||||
const castedState = forceNumber(state)
|
||||
|
||||
return castedState === VideoState.PUBLISHED || castedState === VideoState.WAITING_FOR_LIVE || castedState === VideoState.LIVE_ENDED
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import validator from 'validator'
|
|||
import { pageToStartAndCount } from '@server/helpers/core-utils'
|
||||
import { ACTIVITY_PUB } from '@server/initializers/constants'
|
||||
import { ResultList } from '@shared/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
type ActivityPubCollectionPaginationHandler = (start: number, count: number) => Bluebird<ResultList<any>> | Promise<ResultList<any>>
|
||||
|
||||
|
@ -33,7 +34,7 @@ async function activityPubCollectionPagination (
|
|||
let prev: string | undefined
|
||||
|
||||
// Assert page is a number
|
||||
page = parseInt(page, 10)
|
||||
page = forceNumber(page)
|
||||
|
||||
// There are more results
|
||||
if (result.total > page * size) {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import express from 'express'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { PAGINATION } from '../initializers/constants'
|
||||
|
||||
function setDefaultPagination (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
if (!req.query.start) req.query.start = 0
|
||||
else req.query.start = parseInt(req.query.start, 10)
|
||||
else req.query.start = forceNumber(req.query.start)
|
||||
|
||||
if (!req.query.count) req.query.count = PAGINATION.GLOBAL.COUNT.DEFAULT
|
||||
else req.query.count = parseInt(req.query.count, 10)
|
||||
else req.query.count = forceNumber(req.query.count)
|
||||
|
||||
return next()
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
|||
import { AbuseCreate, UserRight } from '@shared/models'
|
||||
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
|
||||
import { areValidationErrors, doesAbuseExist, doesAccountIdExist, doesCommentIdExist, doesVideoExist } from './shared'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
const abuseReportValidator = [
|
||||
body('account.id')
|
||||
|
@ -216,7 +217,7 @@ const deleteAbuseMessageValidator = [
|
|||
const user = res.locals.oauth.token.user
|
||||
const abuse = res.locals.abuse
|
||||
|
||||
const messageId = parseInt(req.params.messageId + '', 10)
|
||||
const messageId = forceNumber(req.params.messageId)
|
||||
const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
|
||||
|
||||
if (!abuseMessage) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import express from 'express'
|
||||
import { body, param, query } from 'express-validator'
|
||||
import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
|
||||
import {
|
||||
exists,
|
||||
|
@ -171,7 +172,7 @@ const removeVideoRedundancyValidator = [
|
|||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
const redundancy = await VideoRedundancyModel.loadByIdWithVideo(parseInt(req.params.redundancyId, 10))
|
||||
const redundancy = await VideoRedundancyModel.loadByIdWithVideo(forceNumber(req.params.redundancyId))
|
||||
if (!redundancy) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.NOT_FOUND_404,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { Response } from 'express'
|
||||
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
async function doesAbuseExist (abuseId: number | string, res: Response) {
|
||||
const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10))
|
||||
const abuse = await AbuseModel.loadByIdWithReporter(forceNumber(abuseId))
|
||||
|
||||
if (!abuse) {
|
||||
res.fail({
|
||||
|
|
|
@ -2,10 +2,11 @@ import { Response } from 'express'
|
|||
import { AccountModel } from '@server/models/account/account'
|
||||
import { UserModel } from '@server/models/user/user'
|
||||
import { MAccountDefault } from '@server/types/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
|
||||
function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) {
|
||||
const promise = AccountModel.load(parseInt(id + '', 10))
|
||||
const promise = AccountModel.load(forceNumber(id))
|
||||
|
||||
return doesAccountExist(promise, res, sendNotFound)
|
||||
}
|
||||
|
@ -40,7 +41,7 @@ async function doesAccountExist (p: Promise<MAccountDefault>, res: Response, sen
|
|||
}
|
||||
|
||||
async function doesUserFeedTokenCorrespond (id: number, token: string, res: Response) {
|
||||
const user = await UserModel.loadByIdWithChannels(parseInt(id + '', 10))
|
||||
const user = await UserModel.loadByIdWithChannels(forceNumber(id))
|
||||
|
||||
if (token !== user.feedToken) {
|
||||
res.fail({
|
||||
|
|
|
@ -2,10 +2,11 @@ import express from 'express'
|
|||
import { ActorModel } from '@server/models/actor/actor'
|
||||
import { UserModel } from '@server/models/user/user'
|
||||
import { MUserDefault } from '@server/types/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
|
||||
function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) {
|
||||
const id = parseInt(idArg + '', 10)
|
||||
const id = forceNumber(idArg)
|
||||
return checkUserExist(() => UserModel.loadByIdWithChannels(id, withStats), res)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import express from 'express'
|
||||
import { VideoCommentModel } from '@server/models/video/video-comment'
|
||||
import { MVideoId } from '@server/types/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode, ServerErrorCode } from '@shared/models'
|
||||
|
||||
async function doesVideoCommentThreadExist (idArg: number | string, video: MVideoId, res: express.Response) {
|
||||
const id = parseInt(idArg + '', 10)
|
||||
const id = forceNumber(idArg)
|
||||
const videoComment = await VideoCommentModel.loadById(id)
|
||||
|
||||
if (!videoComment) {
|
||||
|
@ -33,7 +34,7 @@ async function doesVideoCommentThreadExist (idArg: number | string, video: MVide
|
|||
}
|
||||
|
||||
async function doesVideoCommentExist (idArg: number | string, video: MVideoId, res: express.Response) {
|
||||
const id = parseInt(idArg + '', 10)
|
||||
const id = forceNumber(idArg)
|
||||
const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id)
|
||||
|
||||
if (!videoComment) {
|
||||
|
@ -57,7 +58,7 @@ async function doesVideoCommentExist (idArg: number | string, video: MVideoId, r
|
|||
}
|
||||
|
||||
async function doesCommentIdExist (idArg: number | string, res: express.Response) {
|
||||
const id = parseInt(idArg + '', 10)
|
||||
const id = forceNumber(idArg)
|
||||
const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id)
|
||||
|
||||
if (!videoComment) {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import express from 'express'
|
||||
import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
|
||||
async function doesChangeVideoOwnershipExist (idArg: number | string, res: express.Response) {
|
||||
const id = parseInt(idArg + '', 10)
|
||||
const id = forceNumber(idArg)
|
||||
const videoChangeOwnership = await VideoChangeOwnershipModel.load(id)
|
||||
|
||||
if (!videoChangeOwnership) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import express from 'express'
|
||||
import { body, param, query } from 'express-validator'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models'
|
||||
import { exists, isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
|
||||
import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
|
||||
|
@ -515,7 +516,7 @@ const usersCheckCurrentPasswordFactory = (targetUserIdGetter: (req: express.Requ
|
|||
|
||||
const user = res.locals.oauth.token.User
|
||||
const isAdminOrModerator = user.role === UserRole.ADMINISTRATOR || user.role === UserRole.MODERATOR
|
||||
const targetUserId = parseInt(targetUserIdGetter(req) + '')
|
||||
const targetUserId = forceNumber(targetUserIdGetter(req))
|
||||
|
||||
// Admin/moderator action on another user, skip the password check
|
||||
if (isAdminOrModerator && targetUserId !== user.id) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { isResolvingToUnicastOnly } from '@server/helpers/dns'
|
|||
import { isPreImportVideoAccepted } from '@server/lib/moderation'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { MUserAccountId, MVideoImport } from '@server/types/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { HttpStatusCode, UserRight, VideoImportState } from '@shared/models'
|
||||
import { VideoImportCreate } from '@shared/models/videos/import/video-import-create.model'
|
||||
import { isIdValid, toIntOrNull } from '../../../helpers/custom-validators/misc'
|
||||
|
@ -130,7 +131,7 @@ const videoImportCancelValidator = [
|
|||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
if (!await doesVideoImportExist(parseInt(req.params.id), res)) return
|
||||
if (!await doesVideoImportExist(forceNumber(req.params.id), res)) return
|
||||
if (!checkUserCanManageImport(res.locals.oauth.token.user, res.locals.videoImport, res)) return
|
||||
|
||||
if (res.locals.videoImport.state !== VideoImportState.PENDING) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import express from 'express'
|
|||
import { body, param, query, ValidationChain } from 'express-validator'
|
||||
import { ExpressPromiseHandler } from '@server/types/express-handler'
|
||||
import { MUserAccountId } from '@server/types/models'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import {
|
||||
HttpStatusCode,
|
||||
UserRight,
|
||||
|
@ -258,7 +259,7 @@ const videoPlaylistElementAPGetValidator = [
|
|||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
const playlistElementId = parseInt(req.params.playlistElementId + '', 10)
|
||||
const playlistElementId = forceNumber(req.params.playlistElementId)
|
||||
const playlistId = req.params.playlistId
|
||||
|
||||
const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
import { exists } from '@server/helpers/custom-validators/misc'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models'
|
||||
import { buildBlockedAccountSQL, buildDirectionAndField } from '../utils'
|
||||
|
||||
|
@ -135,12 +136,12 @@ function buildAbuseListQuery (options: BuildAbusesQueryOptions, type: 'count' |
|
|||
}
|
||||
|
||||
if (exists(options.count)) {
|
||||
const count = parseInt(options.count + '', 10)
|
||||
const count = forceNumber(options.count)
|
||||
suffix += `LIMIT ${count} `
|
||||
}
|
||||
|
||||
if (exists(options.start)) {
|
||||
const start = parseInt(options.start + '', 10)
|
||||
const start = forceNumber(options.start)
|
||||
suffix += `OFFSET ${start} `
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
import { activityPubContextify } from '@server/lib/activitypub/context'
|
||||
import { getBiggestActorImage } from '@server/lib/actor-image'
|
||||
import { ModelCache } from '@server/models/model-cache'
|
||||
import { getLowercaseExtension } from '@shared/core-utils'
|
||||
import { forceNumber, getLowercaseExtension } from '@shared/core-utils'
|
||||
import { ActivityIconObject, ActivityPubActorType, ActorImageType } from '@shared/models'
|
||||
import { AttributesOnly } from '@shared/typescript-utils'
|
||||
import {
|
||||
|
@ -446,7 +446,7 @@ export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> {
|
|||
}
|
||||
|
||||
static rebuildFollowsCount (ofId: number, type: 'followers' | 'following', transaction?: Transaction) {
|
||||
const sanitizedOfId = parseInt(ofId + '', 10)
|
||||
const sanitizedOfId = forceNumber(ofId)
|
||||
const where = { id: sanitizedOfId }
|
||||
|
||||
let columnToUpdate: string
|
||||
|
|
|
@ -2,6 +2,7 @@ import { ModelIndexesOptions, Op, WhereOptions } from 'sequelize'
|
|||
import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
|
||||
import { getBiggestActorImage } from '@server/lib/actor-image'
|
||||
import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { uuidToShort } from '@shared/extra-utils'
|
||||
import { UserNotification, UserNotificationType } from '@shared/models'
|
||||
import { AttributesOnly } from '@shared/typescript-utils'
|
||||
|
@ -284,7 +285,7 @@ export class UserNotificationModel extends Model<Partial<AttributesOnly<UserNoti
|
|||
}
|
||||
|
||||
static removeNotificationsOf (options: { id: number, type: 'account' | 'server', forUserId?: number }) {
|
||||
const id = parseInt(options.id + '', 10)
|
||||
const id = forceNumber(options.id)
|
||||
|
||||
function buildAccountWhereQuery (base: string) {
|
||||
const whereSuffix = options.forUserId
|
||||
|
|
|
@ -70,6 +70,7 @@ import { VideoImportModel } from '../video/video-import'
|
|||
import { VideoLiveModel } from '../video/video-live'
|
||||
import { VideoPlaylistModel } from '../video/video-playlist'
|
||||
import { UserNotificationSettingModel } from './user-notification-setting'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
enum ScopeNames {
|
||||
FOR_ME_API = 'FOR_ME_API',
|
||||
|
@ -900,27 +901,27 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
|
|||
videoQuotaDaily: this.videoQuotaDaily,
|
||||
|
||||
videoQuotaUsed: videoQuotaUsed !== undefined
|
||||
? parseInt(videoQuotaUsed + '', 10) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id)
|
||||
? forceNumber(videoQuotaUsed) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id)
|
||||
: undefined,
|
||||
|
||||
videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined
|
||||
? parseInt(videoQuotaUsedDaily + '', 10) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id)
|
||||
? forceNumber(videoQuotaUsedDaily) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id)
|
||||
: undefined,
|
||||
|
||||
videosCount: videosCount !== undefined
|
||||
? parseInt(videosCount + '', 10)
|
||||
? forceNumber(videosCount)
|
||||
: undefined,
|
||||
abusesCount: abusesCount
|
||||
? parseInt(abusesCount, 10)
|
||||
? forceNumber(abusesCount)
|
||||
: undefined,
|
||||
abusesAcceptedCount: abusesAcceptedCount
|
||||
? parseInt(abusesAcceptedCount, 10)
|
||||
? forceNumber(abusesAcceptedCount)
|
||||
: undefined,
|
||||
abusesCreatedCount: abusesCreatedCount !== undefined
|
||||
? parseInt(abusesCreatedCount + '', 10)
|
||||
? forceNumber(abusesCreatedCount)
|
||||
: undefined,
|
||||
videoCommentsCount: videoCommentsCount !== undefined
|
||||
? parseInt(videoCommentsCount + '', 10)
|
||||
? forceNumber(videoCommentsCount)
|
||||
: undefined,
|
||||
|
||||
noInstanceConfigWarningModal: this.noInstanceConfigWarningModal,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { literal, Op, OrderItem, Sequelize } from 'sequelize'
|
||||
import validator from 'validator'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
type SortType = { sortModel: string, sortValue: string }
|
||||
|
||||
|
@ -202,7 +203,7 @@ function buildBlockedAccountSQLOptimized (columnNameJoin: string, blockerIds: nu
|
|||
}
|
||||
|
||||
function buildServerIdsFollowedBy (actorId: any) {
|
||||
const actorIdNumber = parseInt(actorId + '', 10)
|
||||
const actorIdNumber = forceNumber(actorId)
|
||||
|
||||
return '(' +
|
||||
'SELECT "actor"."serverId" FROM "actorFollow" ' +
|
||||
|
@ -218,7 +219,7 @@ function buildWhereIdOrUUID (id: number | string) {
|
|||
function parseAggregateResult (result: any) {
|
||||
if (!result) return 0
|
||||
|
||||
const total = parseInt(result + '', 10)
|
||||
const total = forceNumber(result)
|
||||
if (isNaN(total)) return 0
|
||||
|
||||
return total
|
||||
|
|
|
@ -6,6 +6,7 @@ import { buildDirectionAndField, createSafeIn, parseRowCountResult } from '@serv
|
|||
import { MUserAccountId, MUserId } from '@server/types/models'
|
||||
import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models'
|
||||
import { AbstractRunQuery } from '../../../shared/abstract-run-query'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -689,12 +690,12 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
|
|||
}
|
||||
|
||||
private setLimit (countArg: number) {
|
||||
const count = parseInt(countArg + '', 10)
|
||||
const count = forceNumber(countArg)
|
||||
this.limit = `LIMIT ${count}`
|
||||
}
|
||||
|
||||
private setOffset (startArg: number) {
|
||||
const start = parseInt(startArg + '', 10)
|
||||
const start = forceNumber(startArg)
|
||||
this.offset = `OFFSET ${start}`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
} from 'sequelize-typescript'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { MAccountActor } from '@server/types/models'
|
||||
import { pick } from '@shared/core-utils'
|
||||
import { forceNumber, pick } from '@shared/core-utils'
|
||||
import { AttributesOnly } from '@shared/typescript-utils'
|
||||
import { ActivityPubActor } from '../../../shared/models/activitypub'
|
||||
import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos'
|
||||
|
@ -280,7 +280,7 @@ export type SummaryOptions = {
|
|||
]
|
||||
},
|
||||
[ScopeNames.WITH_STATS]: (options: AvailableWithStatsOptions = { daysPrior: 30 }) => {
|
||||
const daysPrior = parseInt(options.daysPrior + '', 10)
|
||||
const daysPrior = forceNumber(options.daysPrior)
|
||||
|
||||
return {
|
||||
attributes: {
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
MVideoPlaylistElementVideoUrlPlaylistPrivacy,
|
||||
MVideoPlaylistVideoThumbnail
|
||||
} from '@server/types/models/video/video-playlist-element'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { AttributesOnly } from '@shared/typescript-utils'
|
||||
import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
|
||||
import { VideoPrivacy } from '../../../shared/models/videos'
|
||||
|
@ -185,7 +186,9 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide
|
|||
playlistId: number | string,
|
||||
playlistElementId: number
|
||||
): Promise<MVideoPlaylistElementVideoUrlPlaylistPrivacy> {
|
||||
const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
|
||||
const playlistWhere = validator.isUUID('' + playlistId)
|
||||
? { uuid: playlistId }
|
||||
: { id: playlistId }
|
||||
|
||||
const query = {
|
||||
include: [
|
||||
|
@ -262,13 +265,15 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide
|
|||
.then(position => position ? position + 1 : 1)
|
||||
}
|
||||
|
||||
static reassignPositionOf (
|
||||
videoPlaylistId: number,
|
||||
firstPosition: number,
|
||||
endPosition: number,
|
||||
newPosition: number,
|
||||
static reassignPositionOf (options: {
|
||||
videoPlaylistId: number
|
||||
firstPosition: number
|
||||
endPosition: number
|
||||
newPosition: number
|
||||
transaction?: Transaction
|
||||
) {
|
||||
}) {
|
||||
const { videoPlaylistId, firstPosition, endPosition, newPosition, transaction } = options
|
||||
|
||||
const query = {
|
||||
where: {
|
||||
videoPlaylistId,
|
||||
|
@ -281,7 +286,7 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide
|
|||
validate: false // We use a literal to update the position
|
||||
}
|
||||
|
||||
const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`)
|
||||
const positionQuery = Sequelize.literal(`${forceNumber(newPosition)} + "position" - ${forceNumber(firstPosition)}`)
|
||||
return VideoPlaylistElementModel.update({ position: positionQuery }, query)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { literal, Op, QueryTypes, Transaction } from 'sequelize'
|
||||
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { AttributesOnly } from '@shared/typescript-utils'
|
||||
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
||||
import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
||||
|
@ -123,7 +124,7 @@ export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareMode
|
|||
}
|
||||
|
||||
static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Promise<MActorDefault[]> {
|
||||
const safeOwnerId = parseInt(actorOwnerId + '', 10)
|
||||
const safeOwnerId = forceNumber(actorOwnerId)
|
||||
|
||||
// /!\ On actor model
|
||||
const query = {
|
||||
|
@ -148,7 +149,7 @@ export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareMode
|
|||
}
|
||||
|
||||
static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Promise<MActorDefault[]> {
|
||||
const safeChannelId = parseInt(videoChannelId + '', 10)
|
||||
const safeChannelId = forceNumber(videoChannelId)
|
||||
|
||||
// /!\ On actor model
|
||||
const query = {
|
||||
|
|
|
@ -2,7 +2,7 @@ import CliTable3 from 'cli-table3'
|
|||
import { Command, program } from 'commander'
|
||||
import { URL } from 'url'
|
||||
import validator from 'validator'
|
||||
import { uniqify } from '@shared/core-utils'
|
||||
import { forceNumber, uniqify } from '@shared/core-utils'
|
||||
import { HttpStatusCode, VideoRedundanciesTarget } from '@shared/models'
|
||||
import { assignToken, buildServer, getServerCredentials } from './cli'
|
||||
|
||||
|
@ -138,7 +138,7 @@ async function removeRedundancyCLI (options: { video: number }, command: Command
|
|||
process.exit(-1)
|
||||
}
|
||||
|
||||
const videoId = parseInt(options.video + '', 10)
|
||||
const videoId = forceNumber(options.video)
|
||||
|
||||
const myVideoRedundancies = await server.redundancy.listVideos({ target: 'my-videos' })
|
||||
let videoRedundancy = myVideoRedundancies.data.find(r => videoId === r.id)
|
||||
|
|
|
@ -2,6 +2,7 @@ export * from './array'
|
|||
export * from './random'
|
||||
export * from './date'
|
||||
export * from './env'
|
||||
export * from './number'
|
||||
export * from './object'
|
||||
export * from './path'
|
||||
export * from './regexp'
|
||||
|
|
7
shared/core-utils/common/number.ts
Normal file
7
shared/core-utils/common/number.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
function forceNumber (value: any) {
|
||||
return parseInt(value + '')
|
||||
}
|
||||
|
||||
export {
|
||||
forceNumber
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { ffprobe, FfprobeData } from 'fluent-ffmpeg'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { VideoFileMetadata, VideoResolution } from '@shared/models/videos'
|
||||
|
||||
/**
|
||||
|
@ -55,7 +56,7 @@ async function getAudioStream (videoPath: string, existingProbe?: FfprobeData) {
|
|||
return {
|
||||
absolutePath: data.format.filename,
|
||||
audioStream,
|
||||
bitrate: parseInt(audioStream['bit_rate'] + '', 10)
|
||||
bitrate: forceNumber(audioStream['bit_rate'])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { QueryTypes, Sequelize } from 'sequelize'
|
||||
import { forceNumber } from '@shared/core-utils'
|
||||
import { AbstractCommand } from '../shared'
|
||||
|
||||
export class SQLCommand extends AbstractCommand {
|
||||
|
@ -63,7 +64,7 @@ export class SQLCommand extends AbstractCommand {
|
|||
|
||||
if (!total) return 0
|
||||
|
||||
return parseInt(total + '', 10)
|
||||
return forceNumber(total)
|
||||
}
|
||||
|
||||
getActorImage (filename: string) {
|
||||
|
|
Loading…
Reference in a new issue