diff --git a/service/fling/src/main/java/net/friedl/fling/FlingConfiguration.java b/service/fling/src/main/java/net/friedl/fling/FlingConfiguration.java index 485d4e4..ceff877 100644 --- a/service/fling/src/main/java/net/friedl/fling/FlingConfiguration.java +++ b/service/fling/src/main/java/net/friedl/fling/FlingConfiguration.java @@ -16,7 +16,6 @@ import net.friedl.fling.model.json.PathSerializer; @Configuration public class FlingConfiguration { - @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); diff --git a/service/fling/src/main/java/net/friedl/fling/controller/ArtifactController.java b/service/fling/src/main/java/net/friedl/fling/controller/ArtifactController.java index e6e126f..7cedd55 100644 --- a/service/fling/src/main/java/net/friedl/fling/controller/ArtifactController.java +++ b/service/fling/src/main/java/net/friedl/fling/controller/ArtifactController.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; @@ -32,6 +33,8 @@ import net.friedl.fling.service.archive.ArchiveService; @SecurityRequirement(name = "bearer") @Validated public class ArtifactController { + @Value("${fling.max-artifact-size:-1}") + private Long maxArtifactSize; private ArtifactService artifactService; private ArchiveService archiveService; @@ -58,6 +61,10 @@ public class ArtifactController { @PostMapping(path = "/{id}/data") public void uploadArtifactData(@PathVariable UUID id, HttpServletRequest request) throws IOException { + if(maxArtifactSize >= 0 && maxArtifactSize < request.getContentLengthLong()) { + throw new IOException("Maximum artifact size exceeded"); + } + archiveService.storeArtifact(id, request.getInputStream()); } diff --git a/service/fling/src/main/resources/META-INF/spring-configuration-metadata.json b/service/fling/src/main/resources/META-INF/spring-configuration-metadata.json index fd20a97..38cf357 100644 --- a/service/fling/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/service/fling/src/main/resources/META-INF/spring-configuration-metadata.json @@ -70,6 +70,12 @@ "type": "java.util.Long", "description": "Time until JWT tokens expire", "sourceType": "net.friedl.fling.security.FlingWebSecurityConfiguration" + }, + { + "name": "fling.max-artifact-size", + "type": "java.util.Long", + "description": "Maximum artifact size in bytes. -1 to disable.", + "sourceType": "net.friedl.fling.controller.ArtifactController" } ] } \ No newline at end of file diff --git a/service/fling/src/main/resources/application-local.yml b/service/fling/src/main/resources/application-local.yml index 43108ed..1ea4f2d 100644 --- a/service/fling/src/main/resources/application-local.yml +++ b/service/fling/src/main/resources/application-local.yml @@ -11,7 +11,7 @@ spring: servlet: multipart.max-file-size: -1 multipart.max-request-size: -1 - + logging.level: root: WARN net.friedl: TRACE @@ -21,6 +21,7 @@ logging.level: # spring.http.log-request-details: true fling: + max-artifact-size: 209715200 # 200 MB archive.filesystem.archive-path: /home/armin/Desktop/fling security: allowed-origins: diff --git a/service/fling/src/main/resources/application-prod.yml b/service/fling/src/main/resources/application-prod.yml index d7bdb3e..389537b 100644 --- a/service/fling/src/main/resources/application-prod.yml +++ b/service/fling/src/main/resources/application-prod.yml @@ -16,6 +16,7 @@ logging.level: root: WARN fling: + max-artifact-size: 209715200 # 200 MB archive.filesystem.archive-path: "/var/fling/files" security: allowed-origins: diff --git a/web/fling/.env b/web/fling/.env index e605af4..f01232d 100644 --- a/web/fling/.env +++ b/web/fling/.env @@ -1,2 +1,3 @@ REACT_APP_API=https://fling.friedl.net REACT_APP_LOGLEVEL=warn +REACT_APP_FILESIZE=209715200 diff --git a/web/fling/.env.development.local b/web/fling/.env.development.local index ecf9b5b..3d23ba8 100644 --- a/web/fling/.env.development.local +++ b/web/fling/.env.development.local @@ -1,2 +1,4 @@ REACT_APP_API=http://localhost:8080/ REACT_APP_LOGLEVEL=trace +REACT_APP_FILESIZE=209715200 + diff --git a/web/fling/package-lock.json b/web/fling/package-lock.json index dd87126..f3f2f9b 100644 --- a/web/fling/package-lock.json +++ b/web/fling/package-lock.json @@ -13376,6 +13376,11 @@ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, + "vanillatoasts": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vanillatoasts/-/vanillatoasts-1.4.0.tgz", + "integrity": "sha512-DVMPPWVVt/x1B2f4iVpCw3rYDceu1PGRV8ECc3OfUC8By6O14OdXWjKryfaz8UorBuNe8btDIsujp6YP6gDNGA==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/web/fling/package.json b/web/fling/package.json index 62946c6..6e521cc 100644 --- a/web/fling/package.json +++ b/web/fling/package.json @@ -22,7 +22,8 @@ "react-scripts": "3.4.1", "redux": "^4.0.5", "redux-thunk": "^2.3.0", - "spectre.css": "^0.5.8" + "spectre.css": "^0.5.8", + "vanillatoasts": "^1.4.0" }, "scripts": { "start": "react-scripts start", diff --git a/web/fling/src/components/admin/FlingArtifacts.jsx b/web/fling/src/components/admin/FlingArtifacts.jsx index 0e71e5b..6b26de1 100644 --- a/web/fling/src/components/admin/FlingArtifacts.jsx +++ b/web/fling/src/components/admin/FlingArtifacts.jsx @@ -100,7 +100,9 @@ export default function FlingArtifacts() { .then(result => { log.debug(`Got ${result.length} artifacts`); for (let artifact of result) { - artifacts.push(); + if(artifact.archived) { + artifacts.push(); + } } setArtifacts(artifacts); diff --git a/web/fling/src/components/admin/Upload.jsx b/web/fling/src/components/admin/Upload.jsx index 2996c46..ab174ad 100644 --- a/web/fling/src/components/admin/Upload.jsx +++ b/web/fling/src/components/admin/Upload.jsx @@ -1,4 +1,5 @@ import log from 'loglevel'; +import VanillaToasts from 'vanillatoasts'; import React, { useState, useEffect, useRef } from 'react'; import { useSelector } from "react-redux"; @@ -81,9 +82,21 @@ export default function Upload() { stopEvent(ev); ev.persist(); - let evFiles = ev.dataTransfer.files; + let maxSize = process.env.REACT_APP_FILESIZE; + let evFiles = fileListToArray(ev.dataTransfer.files); - if (!evFiles) { + for (let i = evFiles.length - 1; i >= 0; i--) { + if (maxSize && maxSize >= 0 && evFiles[i].size > maxSize) { + VanillaToasts.create({ + title: "Maximum file size exceeded", + text: `${evFiles[i].name} exceeds the maximum file size of ${prettifyBytes(maxSize)}`, + type: "warning" + }); + evFiles.splice(i, 1); + }; + } + + if (evFiles.lenght === 0) { console.warn("Dropzone triggered without files"); return; } @@ -198,6 +211,7 @@ export default function Upload() {
Total Size: {totalSize()} + {`Max: ${prettifyBytes(process.env.REACT_APP_FILESIZE)}`}
diff --git a/web/fling/src/components/user/FlingUserList.jsx b/web/fling/src/components/user/FlingUserList.jsx index 9d213c3..ccb6a66 100644 --- a/web/fling/src/components/user/FlingUserList.jsx +++ b/web/fling/src/components/user/FlingUserList.jsx @@ -1,4 +1,5 @@ import log from 'loglevel'; +import VanillaToasts from 'vanillatoasts'; import React, { useState, useEffect, useRef } from 'react'; import { Switch, Route, useLocation, Link } from "react-router-dom"; @@ -17,7 +18,10 @@ function Artifacts(props) { let flingClient = new FlingClient(); flingClient.getArtifacts(props.fling.id) - .then(artifacts => setArtifacts(artifacts)); + .then(artifacts => { + artifacts = artifacts.filter(a => a.archived) + setArtifacts(artifacts) + }); }, [props.fling]); function renderArtifact(artifact) { @@ -119,9 +123,21 @@ function Upload(props) { stopEvent(ev); ev.persist(); - let evFiles = ev.dataTransfer.files; + let maxSize = process.env.REACT_APP_FILESIZE; + let evFiles = fileListToArray(ev.dataTransfer.files); - if (!evFiles) { + for (let i = evFiles.length - 1; i >= 0; i--) { + if (maxSize && maxSize >= 0 && evFiles[i].size > maxSize) { + VanillaToasts.create({ + title: "Maximum file size exceeded", + text: `${evFiles[i].name} exceeds the maximum file size of ${prettifyBytes(maxSize)}`, + type: "warning" + }); + evFiles.splice(i, 1); + }; + } + + if (evFiles.length === 0) { console.warn("Dropzone triggered without files"); return; } @@ -236,6 +252,7 @@ function Upload(props) {
Total Size: {totalSize()} + {`Max: ${prettifyBytes(process.env.REACT_APP_FILESIZE)}`}
@@ -303,10 +320,10 @@ export default function FlingUserList(props) {
  • Files
  • - { props.fling.allowUpload + {props.fling.allowUpload ?
  • - Upload -
  • + Upload + : <> } diff --git a/web/fling/src/index.js b/web/fling/src/index.js index 1172ef8..4f7cc84 100644 --- a/web/fling/src/index.js +++ b/web/fling/src/index.js @@ -14,6 +14,7 @@ import { BrowserRouter } from "react-router-dom"; import App from './App'; +import 'vanillatoasts/vanillatoasts.css'; import "./style/fling.scss"; import * as serviceWorker from './serviceWorker';