Skip to content

Commit

Permalink
fix: limit file upload size (#961)
Browse files Browse the repository at this point in the history
  • Loading branch information
lautarodragan authored May 31, 2019
1 parent f47d130 commit 654eddc
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/api/archives/PostArchive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export const PostArchive = (archiveController: ArchiveController) => async (ctx:
if (!allowedTokens.includes(tokenData.data.meta.name))
throw new IncorrectToken(tokenData.data.meta.name, allowedTokens)

const response = await archiveController.postArchive(user, req, tokenData.data.meta.network)
const contentLength = parseInt(req.headers['content-length'], 10)

const response = await archiveController.postArchive(user, req, tokenData.data.meta.network, contentLength)

ctx.status = 200
ctx.body = response
Expand Down
1 change: 1 addition & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export async function app(localVars: any = {}) {
configuration: {
poeContractAddress: configuration.poeContractAddress,
poeBalanceMinimum: configuration.poeBalanceMinimum,
maximumFileSizeInBytes: configuration.maximumFileSizeInBytes,
},
})

Expand Down
3 changes: 3 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MiB } from './helpers/byteSizes'
import { LoggingConfiguration } from './utils/Logging/Logging'

export const defaultMongodbUrl = 'mongodb://localhost:27017/frost'
Expand Down Expand Up @@ -62,6 +63,7 @@ export interface Configuration
readonly skipVault: boolean
readonly poeContractAddress: string
readonly poeBalanceMinimum: number
readonly maximumFileSizeInBytes: number
}

export const configuration: Configuration = {
Expand Down Expand Up @@ -111,4 +113,5 @@ export const configuration: Configuration = {
loggingPretty: true,
poeContractAddress: '0x0e0989b1f9b8a38983c2ba8053269ca62ec9b195',
poeBalanceMinimum: 1000,
maximumFileSizeInBytes: MiB * 15,
}
10 changes: 8 additions & 2 deletions src/controllers/ArchiveController.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Pino from 'pino'

import { PoetNode } from '../daos/PoetNodeDao'
import { PoeAddressNotVerified, PoeBalanceInsufficient } from '../errors/errors'
import { FileTooBig, PoeAddressNotVerified, PoeBalanceInsufficient } from '../errors/errors'
import { fetchBalance } from '../helpers/ethereum'
import { Network } from '../interfaces/Network'
import { Account } from '../models/Account'
Expand All @@ -11,6 +11,7 @@ export interface ArchiveController {
account: Account,
archive: ReadableStream,
network: Network,
fileSize: number,
) => Promise<any>
}

Expand All @@ -28,6 +29,7 @@ interface Dependencies {
interface Configuration {
readonly poeContractAddress: string
readonly poeBalanceMinimum: number
readonly maximumFileSizeInBytes: number
}

export const ArchiveController = ({
Expand All @@ -39,6 +41,7 @@ export const ArchiveController = ({
configuration: {
poeContractAddress,
poeBalanceMinimum,
maximumFileSizeInBytes,
},
}: Arguments): ArchiveController => {
logger.info({ poeContractAddress, poeBalanceMinimum }, 'ArchiveController Instantiated')
Expand All @@ -47,7 +50,10 @@ export const ArchiveController = ({

const networkToNode = (network: Network) => network === Network.LIVE ? mainnetNode : testnetNode

const postArchive = async (account: Account, archive: ReadableStream, network: Network) => {
const postArchive = async (account: Account, archive: ReadableStream, network: Network, fileSize: number) => {
if (fileSize > maximumFileSizeInBytes)
throw new FileTooBig(fileSize, maximumFileSizeInBytes)

const node = networkToNode(network)

const { id: userId, email, poeAddress, poeAddressVerified } = account
Expand Down
13 changes: 13 additions & 0 deletions src/errors/errors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// tslint:disable:max-classes-per-file

import { byteLengthToHumanReadable } from '../helpers/byteSizes'

export const errors = {
AccountAlreadyExists: {
code: 409,
Expand Down Expand Up @@ -129,3 +131,14 @@ export class PoeBalanceInsufficient extends Error {
super(`Insufficient POE balance. You need at least ${minimum} POE. You currently have ${balance}.`)
}
}

export class FileTooBig extends Error {
status = 403

constructor(size: number, maxSize: number) {
super(
`File too big. Got ${byteLengthToHumanReadable(size)}. ` +
`Max is ${byteLengthToHumanReadable(maxSize)}.`,
)
}
}
17 changes: 17 additions & 0 deletions src/helpers/byteSizes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const KiB = 1024
export const MiB = KiB ** 2
export const GiB = KiB ** 3

const symbolToSize: ReadonlyArray<[string, number]> = [
['B', 1],
['KiB', KiB],
['MiB', MiB],
['GiB', GiB],
]

export const byteLengthToHumanReadable = (byteLength: number, fractionDigits: number = 2) => {
for (let i = symbolToSize.length - 1; i >= 0; i--)
if (byteLength >= symbolToSize[i][1])
return (byteLength / symbolToSize[i][1]).toFixed(fractionDigits) + ' ' + symbolToSize[i][0]
throw new Error('Whoops!')
}

0 comments on commit 654eddc

Please sign in to comment.