0.1 #1
8 changed files with 119 additions and 59 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -26,7 +26,7 @@ function FlingArtifactControl(props) {
|
|||
log.trace(`Generated download url: ${url}`);
|
||||
frame.src = url;
|
||||
iframeContainer.current.appendChild(frame);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 => {
|
||||
|
|
Loading…
Reference in a new issue