Skip to content

Commit

Permalink
feat(application-system): add total file size limit (#14892)
Browse files Browse the repository at this point in the history
* feat: add total file size limit

* feat: add default to component

* Update libs/application/ui-components/src/utilities/FileUploadController/index.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: from comments

* feat: move default total max size to utils

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 4, 2024
1 parent 3db7c20 commit 4b117e0
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 4 deletions.
5 changes: 5 additions & 0 deletions libs/application/core/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ export const hasYes = (answer: any) => {

return answer === YES
}

export const DEFAULT_FILE_SIZE_LIMIT = 10000000 // 10MB
export const DEFAULT_TOTAL_FILE_SIZE_SUM = 100000000 // 100MB, too high?
export const DEFAULT_ALLOWED_FILE_TYPES =
'.pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png, .heic'
12 changes: 9 additions & 3 deletions libs/application/core/src/lib/fieldBuilders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ import {
import { Colors } from '@island.is/island-ui/theme'
import { SpanType, BoxProps } from '@island.is/island-ui/core/types'
import { coreDefaultFieldMessages } from './messages'
import {
DEFAULT_ALLOWED_FILE_TYPES,
DEFAULT_FILE_SIZE_LIMIT,
DEFAULT_TOTAL_FILE_SIZE_SUM,
} from './constants'

const extractCommonFields = (
data: Omit<BaseField, 'type' | 'component' | 'children'>,
Expand Down Expand Up @@ -337,6 +342,7 @@ export function buildFileUploadField(
uploadAccept,
maxSize,
maxSizeErrorText,
totalMaxSize,
forImageUpload,
} = data
return {
Expand All @@ -352,10 +358,10 @@ export function buildFileUploadField(
uploadButtonLabel ||
coreDefaultFieldMessages.defaultFileUploadButtonLabel,
uploadMultiple,
uploadAccept:
uploadAccept ?? '.pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png, .heic',
maxSize: maxSize ?? 10000000,
uploadAccept: uploadAccept ?? DEFAULT_ALLOWED_FILE_TYPES,
maxSize: maxSize ?? DEFAULT_FILE_SIZE_LIMIT,
maxSizeErrorText,
totalMaxSize: totalMaxSize ?? DEFAULT_TOTAL_FILE_SIZE_SUM,
forImageUpload,
type: FieldTypes.FILEUPLOAD,
component: FieldComponents.FILEUPLOAD,
Expand Down
6 changes: 6 additions & 0 deletions libs/application/core/src/lib/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,12 @@ export const coreErrorMessages = defineMessages({
'Skráin er of stór. Hægt er að hlaða inn skrám sem eru {maxSizeInMb}MB eða minni.',
description: 'Error message when file size exceeds max size limit',
},
fileMaxSumSizeLimitExceeded: {
id: 'application.system:core.error.file.maxSizeLimitSumExceeded',
defaultMessage:
'Skrárnar eru samtals of stórar. Hægt er að hlaða inn skrám sem eru samtals {maxSizeInMb}MB eða minni.',
description: 'Error message when sum of file sizes exceeds max size limit',
},
fileInvalidExtension: {
id: 'application.system:core.error.file.invalidExtension',
defaultMessage:
Expand Down
4 changes: 4 additions & 0 deletions libs/application/types/src/lib/Fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ export interface FileUploadField extends BaseField {
*/
readonly maxSize?: number
readonly maxSizeErrorText?: FormText
/**
* Defaults to 100MB
*/
readonly totalMaxSize?: number
readonly forImageUpload?: boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {
DELETE_ATTACHMENT,
} from '@island.is/application/graphql'

import { uploadFileToS3 } from './utils'
import { Action, ActionTypes } from './types'
import { InputImageUpload } from '../../components/InputImageUpload/InputImageUpload'
import { DEFAULT_TOTAL_MAX_SIZE, uploadFileToS3 } from './utils'

type UploadFileAnswer = {
name: string
Expand Down Expand Up @@ -72,6 +72,7 @@ interface FileUploadControllerProps {
readonly accept?: string
readonly maxSize?: number
readonly maxSizeErrorText?: string
readonly totalMaxSize?: number
readonly forImageUpload?: boolean
}

Expand All @@ -88,6 +89,7 @@ export const FileUploadController: FC<
accept,
maxSize,
maxSizeErrorText,
totalMaxSize = DEFAULT_TOTAL_MAX_SIZE,
forImageUpload,
}) => {
const { formatMessage } = useLocale()
Expand All @@ -97,6 +99,7 @@ export const FileUploadController: FC<
const [createUploadUrl] = useMutation(CREATE_UPLOAD_URL)
const [addAttachment] = useMutation(ADD_ATTACHMENT)
const [deleteAttachment] = useMutation(DELETE_ATTACHMENT)
const [sumOfFileSizes, setSumOfFileSizes] = useState(0)
const initialUploadFiles: UploadFile[] =
(val && val.map((f) => answerToUploadFile(f))) || []
const [state, dispatch] = useReducer(reducer, initialUploadFiles)
Expand Down Expand Up @@ -164,6 +167,22 @@ export const FileUploadController: FC<
clearErrors(id)
setUploadError(undefined)

const totalNewFileSize = addedUniqueFiles
.map((f) => f.size)
.reduce((a, b) => a + b, 0)

// Show an error if the sum of the file sizes exceeds totalMaxSize.
if (totalMaxSize && totalNewFileSize + sumOfFileSizes > totalMaxSize) {
setUploadError(
formatMessage(coreErrorMessages.fileMaxSumSizeLimitExceeded, {
maxSizeInMb: totalMaxSize / 1000000,
}),
)
return
}

setSumOfFileSizes(totalNewFileSize + sumOfFileSizes)

const newUploadFiles = addedUniqueFiles.map((f) =>
fileToObject(f, 'uploading'),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { UploadFile } from '@island.is/island-ui/core'

import { S3UploadResponse, ActionTypes, Action } from './types'

export const DEFAULT_TOTAL_MAX_SIZE = 100000000

export const uploadFileToS3 = (
file: UploadFile,
dispatch: React.Dispatch<Action>,
Expand Down

0 comments on commit 4b117e0

Please sign in to comment.