const { start, count } = pageToStartAndCount(page, ACTIVITY_PUB.COLLECTION_ITEMS_PER_PAGE)
const result = await handler(start, count)
- let next: string
- let prev: string
+ let next: string | undefined
+ let prev: string | undefined
// Assert page is a number
page = parseInt(page, 10)
const paths = [ __dirname, '..', '..' ]
// We are under /dist directory
- if (process.mainModule.filename.endsWith('.ts') === false) {
+ if (process.mainModule && process.mainModule.filename.endsWith('.ts') === false) {
paths.push('..')
}
const writeFilePromise = promisify2WithVoid<string, any>(writeFile)
const readdirPromise = promisify1<string, string[]>(readdir)
const mkdirpPromise = promisify1<string, string>(mkdirp)
+// we cannot modify the Promise types, so we should make the promisify instance check mkdirp
const pseudoRandomBytesPromise = promisify1<number, Buffer>(pseudoRandomBytes)
const createPrivateKey = promisify1<number, { key: string }>(pem.createPrivateKey)
const getPublicKey = promisify1<string, { publicKey: string }>(pem.getPublicKey)
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
mimeTypeRegex: string,
field: string,
- maxSize: number,
+ maxSize: number | null,
optional = false
) {
// Should have files
if (!file || !file.originalname) return false
// Check size
- if (maxSize && file.size > maxSize) return false
+ if ((maxSize !== null) && file.size > maxSize) return false
return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
}
}
async function isVideoExist (id: string, res: Response) {
- let video: VideoModel
+ let video: VideoModel | null
if (validator.isInt(id)) {
video = await VideoModel.loadAndPopulateAccountAndServerAndTags(+id)
video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(id)
}
- if (!video) {
+ if (video && video !== null) {
res.status(404)
.json({ error: 'Video not found' })
.end()
async function isVideoChannelOfAccountExist (channelId: number, user: UserModel, res: Response) {
if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
- if (!videoChannel) {
+ if (videoChannel && videoChannel !== null) {
res.status(400)
.json({ error: 'Unknown video video channel on this instance.' })
.end()
}
const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
- if (!videoChannel) {
+ if (videoChannel && videoChannel !== null) {
res.status(400)
.json({ error: 'Unknown video video channel for this account.' })
.end()
}
})
- const fields = []
+ let fields: { name: string, maxCount: number }[] = []
for (const fieldName of fieldNames) {
fields.push({
name: fieldName,
function bunyanLogFactory (level: string) {
return function () {
let meta = null
- let args = [].concat(arguments)
+ let args: any[] = []
+ args.concat(arguments)
if (arguments[ 0 ] instanceof Error) {
meta = arguments[ 0 ].toString()
function isSignupAllowedForCurrentIP (ip: string) {
const addr = ipaddr.parse(ip)
let excludeList = [ 'blacklist' ]
- let matched: string
+ let matched = ''
// if there is a valid, non-empty whitelist, we exclude all unknown adresses too
if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) {
async function getServerActor () {
if (serverActor === undefined) {
const application = await ApplicationModel.load()
+ if (!application) throw Error('Could not application.')
serverActor = application.Account.Actor
}
const cacheDirectories = Object.keys(CACHE)
.map(k => CACHE[k].DIRECTORY)
- const tasks = []
+ const tasks: Promise<string>[] = []
for (const key of Object.keys(storage)) {
const dir = storage[key]
tasks.push(mkdirpPromise(dir))
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { Migration } from '../../models/migrations'
function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.STRING(400),
allowNull: false,
defaultValue: ''
- }
+ } as Migration.String
return q.addColumn('Pods', 'email', data)
.then(() => {
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { Migration } from '../../models/migrations'
function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.STRING(400),
allowNull: false,
defaultValue: ''
- }
+ } as Migration.String
return q.addColumn('Users', 'email', data)
.then(() => {
const query = 'UPDATE "Users" SET "email" = CONCAT("username", \'@example.com\')'
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { Migration } from '../../models/migrations'
function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0
- }
+ } as Migration.Integer
return q.addColumn('Videos', 'category', data)
.then(() => {
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { Migration } from '../../models/migrations'
function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0
- }
+ } as Migration.Integer
return q.addColumn('Videos', 'licence', data)
.then(() => {
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { Migration } from '../../models/migrations'
function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
- }
+ } as Migration.Boolean
return q.addColumn('Videos', 'nsfw', data)
.then(() => {
return utils.sequelize.query(query)
})
.then(() => {
- dataUUID.defaultValue = null
+ dataUUID.defaultValue = null // FIXME:default value cannot be null if string
return q.changeColumn('Videos', 'uuid', dataUUID)
})
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { Migration } from '../../models/migrations'
function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.BIGINT,
allowNull: false,
defaultValue: -1
- }
+ } as Migration.BigInteger
return q.addColumn('Users', 'videoQuota', data)
.then(() => {
import * as Sequelize from 'sequelize'
+import { Migration } from '../../models/migrations'
async function up (utils: {
transaction: Sequelize.Transaction,
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: true
- }
+ } as Migration.Boolean
await utils.queryInterface.addColumn('video', 'commentsEnabled', data)
data.defaultValue = null
import { createClient } from 'redis'
import { CONFIG } from '../constants'
import { JobQueue } from '../../lib/job-queue'
+import { Redis } from '../../lib/redis'
import { initDatabaseModels } from '../database'
async function up (utils: {
await initDatabaseModels(false)
return new Promise((res, rej) => {
- const client = createClient({
- host: CONFIG.REDIS.HOSTNAME,
- port: CONFIG.REDIS.PORT,
- db: CONFIG.REDIS.DB
- })
+ const client = createClient(Redis.getRedisClient())
const jobsPrefix = 'q-' + CONFIG.WEBSERVER.HOST
return res({ type: job.type, payload: parsedData })
} catch (err) {
console.error('Cannot parse data %s.', job.data)
- return res(null)
+ return res(undefined)
}
})
})
// The installer will do that
if (tables.length === 0) return
- let actualVersion: number = null
+ let actualVersion: number | null = null
const [ rows ] = await sequelizeTypescript.query('SELECT "migrationVersion" FROM "application"')
if (rows && rows[0] && rows[0].migrationVersion) {
isOrigin = false
) {
const to = [ ACTIVITY_PUB.PUBLIC ]
- const cc = []
+ const cc: string[] = []
// Owner of the video we comment
if (isOrigin === false) {
}
function buildAudience (followerUrls: string[], isPublic = true) {
- let to = []
- let cc = []
+ let to: string[] = []
+ let cc: string[] = []
if (isPublic) {
to = [ ACTIVITY_PUB.PUBLIC ]
const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED
const duration = videoObject.duration.replace(/[^\d]+/, '')
- let language: string = null
+ let language: string | undefined
if (videoObject.language) {
language = videoObject.language.identifier
}
- let category: number = null
+ let category: number | undefined
if (videoObject.category) {
category = parseInt(videoObject.category.identifier, 10)
}
- let licence: number = null
+ let licence: number | undefined
if (videoObject.licence) {
licence = parseInt(videoObject.licence.identifier, 10)
}
throw new Error('Cannot find video files for ' + videoCreated.url)
}
- const attributes = []
+ const attributes: VideoFileModel[] = []
for (const fileUrl of fileUrls) {
// Fetch associated magnet uri
const magnet = videoObject.url.find(u => {
if (!magnet) throw new Error('Cannot find associated magnet uri for file ' + fileUrl.href)
const parsed = magnetUtil.decode(magnet.href)
- if (!parsed || isVideoFileInfoHashValid(parsed.infoHash) === false) throw new Error('Cannot parse magnet URI ' + magnet.href)
+ if (!parsed ||
+ (parsed.infoHash &&
+ (isVideoFileInfoHashValid(parsed.infoHash) === false))) {
+ throw new Error('Cannot parse magnet URI ' + magnet.href)
+ }
const attribute = {
extname: VIDEO_MIMETYPE_EXT[ fileUrl.mimeType ],
resolution: fileUrl.width,
size: fileUrl.size,
videoId: videoCreated.id
- }
+ } as VideoFileModel
attributes.push(attribute)
}
async addVideoAbuseReport (videoId: number) {
const video = await VideoModel.load(videoId)
+ if (!video) throw new Error('Unknown Video id during Abuse report.')
const text = `Hi,\n\n` +
- `Your instance received an abuse for video the following video ${video.url}\n\n` +
+ `Your instance received an abuse for the following video ${video.url}\n\n` +
`Cheers,\n` +
`PeerTube.`
}
async function buildSignedRequestOptions (payload: { signatureActorId?: number }) {
- let actor: ActorModel
+ let actor: ActorModel | null
if (payload.signatureActorId) {
actor = await ActorModel.load(payload.signatureActorId)
if (!actor) throw new Error('Unknown signature actor id.')
const video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(payload.videoUUID)
// No video, maybe deleted?
if (!video) {
- logger.info('Do not process job %d, video does not exist.', job.id, { videoUUID: video.uuid })
+ logger.info('Do not process job %d, video does not exist.', job.id)
return undefined
}
const video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(payload.videoUUID)
// No video, maybe deleted?
if (!video) {
- logger.info('Do not process job %d, video does not exist.', job.id, { videoUUID: video.uuid })
+ logger.info('Do not process job %d, video does not exist.', job.id)
return undefined
}
// Transcoding in other resolution
if (payload.resolution) {
- await video.transcodeOriginalVideofile(payload.resolution, payload.isPortraitMode)
+ await video.transcodeOriginalVideofile(payload.resolution, payload.isPortraitMode || false)
await retryTransactionWrapper(onVideoFileTranscoderOrImportSuccess, video)
} else {
const queue = this.queues[obj.type]
if (queue === undefined) {
logger.error('Unknown queue %s: cannot create job.', obj.type)
- return
+ throw Error('Unknown queue, cannot create job')
}
const jobArgs: Bull.JobOptions = {
type CachedRoute = {
body: string,
- contentType?: string
- statusCode?: string
+ contentType: string
+ statusCode: string
}
class Redis {
}
setCachedRoute (req: express.Request, body: any, lifetime: number, contentType?: string, statusCode?: number) {
- const cached: CachedRoute = {
- body: body.toString(),
- contentType,
- statusCode: statusCode.toString()
- }
+ const cached: CachedRoute = Object.assign({}, {
+ body: body.toString()
+ },
+ (contentType) ? { contentType } : null,
+ (statusCode) ? { statusCode: statusCode.toString() } : null
+ )
return this.setObject(this.buildCachedRouteKey(req), cached, lifetime)
}
import { buildActorInstance, getAccountActivityPubUrl, setAsyncActorKeys } from './activitypub'
import { createVideoChannel } from './video-channel'
import { VideoChannelModel } from '../models/video/video-channel'
+import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model'
async function createUserAccountAndChannel (userToCreate: UserModel, validateUser = true) {
const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => {
async function createLocalAccountWithoutKeys (
name: string,
- userId: number,
- applicationId: number,
- t: Sequelize.Transaction,
+ userId: number | null,
+ applicationId: number | null,
+ t: Sequelize.Transaction | undefined,
type: ActivityPubActorType= 'Person'
) {
const url = getAccountActivityPubUrl(name)
userId,
applicationId,
actorId: actorInstanceCreated.id
- })
+ } as FilteredModelAttributes<AccountModel>)
const accountInstanceCreated = await accountInstance.save({ transaction: t })
accountInstanceCreated.Actor = actorInstanceCreated
async function createVideoComment (obj: {
text: string,
- inReplyToComment: VideoCommentModel,
+ inReplyToComment: VideoCommentModel | null,
video: VideoModel
account: AccountModel
}, t: Sequelize.Transaction) {
- let originCommentId: number = null
- let inReplyToCommentId: number = null
+ let originCommentId: number | null = null
+ let inReplyToCommentId: number | null = null
- if (obj.inReplyToComment) {
+ if (obj.inReplyToComment && obj.inReplyToComment !== null) {
originCommentId = obj.inReplyToComment.originCommentId || obj.inReplyToComment.id
inReplyToCommentId = obj.inReplyToComment.id
}
}
function setBlacklistSort (req: express.Request, res: express.Response, next: express.NextFunction) {
- let newSort: SortType = { sortModel: undefined, sortValue: undefined }
+ let newSort: SortType = { sortModel: undefined, sortValue: '' }
if (!req.query.sort) req.query.sort = '-createdAt'
if (numberOfActorFollowsRemoved) logger.info('Removed bad %d actor follows.', numberOfActorFollowsRemoved)
}
- static updateActorFollowsScore (goodInboxes: string[], badInboxes: string[], t: Sequelize.Transaction) {
+ static updateActorFollowsScore (goodInboxes: string[], badInboxes: string[], t: Sequelize.Transaction | undefined) {
if (goodInboxes.length === 0 && badInboxes.length === 0) return
logger.info('Updating %d good actor follows and %d bad actor follows scores.', goodInboxes.length, badInboxes.length)
}
}
- private static incrementScores (inboxUrls: string[], value: number, t: Sequelize.Transaction) {
+ private static incrementScores (inboxUrls: string[], value: number, t: Sequelize.Transaction | undefined) {
const inboxUrlsString = inboxUrls.map(url => `'${url}'`).join(',')
const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` +
'WHERE "actor"."inboxUrl" IN (' + inboxUrlsString + ') OR "actor"."sharedInboxUrl" IN (' + inboxUrlsString + ')' +
')'
- const options = {
+ const options = t ? {
type: Sequelize.QueryTypes.BULKUPDATE,
transaction: t
- }
+ } : undefined
return ActorFollowModel.sequelize.query(query, options)
}
--- /dev/null
+import * as Sequelize from 'sequelize'
+
+declare namespace Migration {
+ interface Boolean extends Sequelize.DefineAttributeColumnOptions {
+ defaultValue: boolean | null
+ }
+
+ interface String extends Sequelize.DefineAttributeColumnOptions {
+ defaultValue: string | null
+ }
+
+ interface Integer extends Sequelize.DefineAttributeColumnOptions {
+ defaultValue: number | null
+ }
+
+ interface BigInteger extends Sequelize.DefineAttributeColumnOptions {
+ defaultValue: Sequelize.DataTypeBigInt | number | null
+ }
+}
+
+export {
+ Migration
+}
return OAuthTokenModel.scope(ScopeNames.WITH_ACCOUNT)
.findOne(query)
.then(token => {
- token['user'] = token.User
-
- return token
+ if (token) {
+ token['user'] = token.User
+ return token
+ } else {
+ return new OAuthTokenModel()
+ }
})
}
as: 'InReplyToVideoComment',
onDelete: 'CASCADE'
})
- InReplyToVideoComment: VideoCommentModel
+ InReplyToVideoComment: VideoCommentModel | null
@ForeignKey(() => VideoModel)
@Column
toActivityPubObject (threadParentComments: VideoCommentModel[]): VideoCommentObject {
let inReplyTo: string
// New thread, so in AS we reply to the video
- if (this.inReplyToCommentId === null) {
+ if ((this.inReplyToCommentId !== null) || (this.InReplyToVideoComment !== null)) {
inReplyTo = this.Video.url
} else {
inReplyTo = this.InReplyToVideoComment.url
login,
serverLogin,
userLogin,
- setAccessTokensToServers
+ setAccessTokensToServers,
+ Server,
+ Client,
+ User
}
import {
getClient,
- serverLogin
+ serverLogin,
+ Server,
+ Client,
+ User
} from '../tests/utils/index'
program
throw new Error('All arguments are required.')
}
-const server = {
- url: program['url'],
- user: {
- username: program['username'],
- password: program['password']
- },
- client: {
- id: null,
- secret: null
- }
-}
-
getClient(program.url)
.then(res => {
- server.client.id = res.body.client_id
- server.client.secret = res.body.client_secret
+ const server = {
+ url: program['url'],
+ user: {
+ username: program['username'],
+ password: program['password']
+ } as User,
+ client: {
+ id: res.body.client_id as string,
+ secret: res.body.client_secret as string
+ } as Client
+ } as Server
return serverLogin(server)
})