0.1 #1

Merged
armin merged 30 commits from 0.1 into master 2020-07-26 00:51:55 +00:00
8 changed files with 119 additions and 59 deletions
Showing only changes of commit e9ad499850 - Show all commits

View file

@ -16,13 +16,30 @@ Content-Type: application/json
{"adminName": "admin", "adminPassword":"123"}
-> run-hook (restclient-set-var ":token" (buffer-substring-no-properties 1 (line-end-position)))
:token = Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTUxNzY4OTksImV4cCI6MTU5NTM1Njg5OSwic3ViIjoiYWRtaW4ifQ.uRh_xBCrBiLQEBah9I8bYWM-Zph-V_pzQVdaGSU5Mlc
:token = Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTU2NzUxMjAsImV4cCI6MTU5NTg1NTEyMCwic3ViIjoiYWRtaW4ifQ.WzrGTTZTYHYOw8SskHQ2_sob2tzLIF6q8y8_2oyuafs
# Get all flings
GET http://localhost:8080/api/fling
Content-Type: application/json
:token
:flingid = 9f7353a3-efaa-41af-9f93-61e02dc5e440
# Put a fling
PUT http://localhost:8080/api/fling/:flingid
Content-Type: application/json
:token
{
"id": "9f7353a3-efaa-41af-9f93-61e02dc5e440",
"name": "Shared Fling from querysheetsdfasfd",
"creationTime": 1595253659362,
"shareId": "WWgTlNZJPZDQ6oowUYfxcQqq",
"directDownload": false,
"allowUpload": false,
"shared": true,
"expirationClicks": 12
}
# Add a new fling
POST http://localhost:8080/api/fling
Content-Type: application/json

View file

@ -101,11 +101,14 @@ public class FlingController {
public ResponseEntity<Resource> getFlingData(@PathVariable UUID id) throws IOException {
FlingDto flingDto = flingService.getById(id);
InputStreamResource data = new InputStreamResource(archiveService.getFling(id));
Long length = data.contentLength();
data = new InputStreamResource(archiveService.getFling(id));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=\"" + flingDto.getName() + ".zip" + "\"")
.contentLength(200L) // FIXME
.contentLength(length)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(data);
}

View file

@ -22,7 +22,6 @@ import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import net.friedl.fling.model.dto.AdminAuthDto;
import net.friedl.fling.model.dto.FlingDto;
import net.friedl.fling.model.dto.UserAuthDto;
import net.friedl.fling.persistence.entities.FlingEntity;
import net.friedl.fling.persistence.entities.TokenEntity;

View file

@ -275,7 +275,11 @@ public class FlingControllerTest {
byte[] testZip = new byte[testZipInt.length];
for (int idx = 0; idx < testZip.length; idx++) testZip[idx] = (byte) testZipInt[idx];
when(archiveService.getFling(any())).thenReturn(new ByteArrayInputStream(testZip));
when(archiveService.getFling(any()))
.thenAnswer((invocation) -> {
// need to use thenAnswer here to always return a fresh new (unclosed) input stream
return new ByteArrayInputStream(testZip);
});
mockMvc.perform(get("/api/fling/{id}/data", flingId))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))

View file

@ -26,7 +26,7 @@ function FlingArtifactControl(props) {
log.trace(`Generated download url: ${url}`);
frame.src = url;
iframeContainer.current.appendChild(frame);
})
});
}
return (

View file

@ -1,27 +1,38 @@
import log from 'loglevel';
import React, { useRef, useState, useEffect } from 'react';
import {flingClient} from '../../util/flingclient';
import { AuthClient } from '../../util/fc';
export default function FlingUser(props) {
let iframeContainer = useRef(null);
let [packaging, setPackaging] = useState(true);
let [done, setDone] = useState(false);
let [waitingMessage, setWaitingMessage] = useState("");
let [downloadUrl, setDownloadUrl] = useState("");
useEffect(handleDownload, []);
function handleDownload() {
flingClient.packageFling(props.fling.id)
.then(downloadUrl => {
let authClient = new AuthClient();
authClient.deriveToken({ singleUse: true })
.then(token => {
let url = `${process.env.REACT_APP_API.replace(/\/+$/, '')}/api/fling/${props.fling.id}/data?derivedToken=${token}`;
log.trace(`Generated download url for link: ${url}`);
setDownloadUrl(url);
})
.then(
authClient.deriveToken({ singleUse: true })
.then(token => {
setPackaging(false);
// We need this iframe hack because with a regular href, while
// the browser downloads the file fine, it also reloads the page, hence
// loosing all logs and state
let frame = document.createElement("iframe");
frame.src = downloadUrl;
let url = `${process.env.REACT_APP_API.replace(/\/+$/, '')}/api/fling/${props.fling.id}/data?derivedToken=${token}`;
log.trace(`Generated download url: ${url}`);
frame.src = url;
iframeContainer.current.appendChild(frame);
setDownloadUrl(downloadUrl);
});
}));
let randMsg = ["Please stay patient...",
"Your download will be ready soon...",
@ -30,6 +41,15 @@ export default function FlingUser(props) {
setInterval(() => setWaitingMessage(randMsg[Math.floor(Math.random() * randMsg.length)]), 10000);
}
function invalidateLink(ev) {
setDone(true);
window.location.href = downloadUrl;
}
function reloadPage(ev) {
window.location.reload();
}
return (
<div>
<div className="container-center">
@ -39,10 +59,18 @@ export default function FlingUser(props) {
? <><div className="loading loading-lg" />
{waitingMessage ? waitingMessage : "Packaging up your files..."}
</>
: <>
: !done
? <>
<h5>Your download is <span className="text-primary">ready!</span></h5>
<i className="icon icon-check icon-2x text-primary" /><br />
<span className="text-dark">Download doesn't start? <br/><a href={downloadUrl}>Click here</a></span>
<span className="text-dark">Download doesn't start? <br />
<button className="btn btn-link" onClick={invalidateLink}>Click here</button></span>
</>
: <>
<h5>Thanks for <span className="text-primary">downloading!</span></h5>
<i className="icon icon-check icon-2x text-primary" /><br />
<span className="text-dark">Want to download again? <br />
<button className="btn btn-link" onClick={reloadPage}>Reload page</button></span>
</>
}
</div>

View file

@ -10,18 +10,27 @@ import FlingUserList from './FlingUserList';
export default function FlingUser() {
let { shareId } = useParams();
let [fling, setFling] = useState({});
let [loading, setLoading] = useState(true);
useEffect(() => {
let flingClient = new FlingClient();
flingClient.getFlingByShareId(shareId)
.then(f => setFling(f));
.then(f => {
setFling(f);
setLoading(false);
});
}, [shareId]);
return (
<div>
{fling.sharing && fling.sharing.directDownload
<>
{loading
? <div></div>
: <div>
{fling.shared && fling.directDownload
? <DirectDownload fling={fling} />
: <FlingUserList fling={fling} />}
</div>
}
</>
);
}

View file

@ -12,7 +12,7 @@ export default function Unlock() {
useEffect(() => {
let authClient = new AuthClient();
let userAuth = new fc.UserAuth(location.state.shareId, "")
let userAuth = new fc.UserAuth(location.state.shareId, "");
authClient.authenticateUser({ 'userAuth': userAuth })
.then(response => {
@ -20,7 +20,7 @@ export default function Unlock() {
sessionStorage.setItem('token', response);
history.replace(location.state.from);
}).catch(error => {
log.info("Fling protected. Could not unlock without code.")
log.info("Fling protected. Could not unlock without code.");
});
}, [location, history]);
@ -46,7 +46,7 @@ export default function Unlock() {
function handleSubmit(ev) {
ev.preventDefault();
let authClient = new AuthClient();
let userAuth = new fc.UserAuth(shareId, authCode)
let userAuth = new fc.UserAuth(shareId, authCode);
authClient.authenticateUser({ 'userAuth': userAuth })
.then(response => {