Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
4rthem committed Oct 4, 2023
1 parent 51d33c0 commit 7f7943a
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 118 deletions.
2 changes: 1 addition & 1 deletion uploader/api/src/Entity/Commit.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class Commit extends AbstractUuidEntity
private ?string $totalSize = null;

#[ORM\Column(type: Types::JSON)]
#[Groups(['asset:read', 'commit:read'])]
#[Groups(['asset:read', 'commit:read', 'commit:write'])]
private array $formData = [];

#[Groups(['asset:read', 'commit:read', 'commit:write'])]
Expand Down
22 changes: 12 additions & 10 deletions uploader/client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import AuthError from "./components/page/AuthError";
import SelectTarget from "./components/page/SelectTarget";
import {DashboardMenu} from "@alchemy/react-ps";
import FullPageLoader from "./components/FullPageLoader";
import {authenticatedRequest} from "./lib/api";
import apiClient from "./lib/api";

class App extends Component {
state = {
Expand Down Expand Up @@ -45,10 +45,12 @@ class App extends Component {

authenticate = async () => {
this.setState({authenticating: true});
await authenticatedRequest({
url: '/me',
});
this.setState({authenticating: false});
const user = (await apiClient.get('/me')).data;

this.setState({
user,
authenticating: false,
})
}

handleStateChange(state) {
Expand All @@ -65,7 +67,7 @@ class App extends Component {

render() {
const {user} = this.state;
const perms = user && user.permissions;
const perms = user?.permissions ?? {};

return <Router>
{config.displayServicesMenu && <DashboardMenu
Expand All @@ -82,9 +84,9 @@ class App extends Component {
email={this.state.user.email}
/> : ''}
<Link onClick={() => this.closeMenu()} to="/" className="menu-item">Home</Link>
{perms && perms.form_schema ?
{perms.form_schema ?
<Link onClick={() => this.closeMenu()} to="/form-editor">Form editor</Link> : ''}
{perms && perms.target_data ?
{perms.target_data ?
<Link onClick={() => this.closeMenu()} to="/target-data-editor">Target data editor</Link> : ''}
{oauthClient.isAuthenticated() ?
<a onClick={this.logout} href={'javascript:void(0)'}>Logout</a>
Expand All @@ -97,8 +99,8 @@ class App extends Component {
<PrivateRoute path="/download/:id" exact component={Download}/>
<Route path="/login" exact component={Login}/>
<Route path="/auth-error" exact component={AuthError}/>
{perms && perms.form_schema ? <PrivateRoute path="/form-editor" exact component={FormEditor}/> : ''}
{perms && perms.target_data ?
{perms.form_schema ? <PrivateRoute path="/form-editor" exact component={FormEditor}/> : ''}
{perms.target_data ?
<PrivateRoute path="/target-data-editor" exact component={TargetDataEditor}/> : ''}
</div>
</Router>
Expand Down
12 changes: 4 additions & 8 deletions uploader/client/src/actions/download.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import {authenticatedRequest} from "../lib/api";
import apiClient from "../lib/api";

export function Download(url, callback, errCallback) {
authenticatedRequest({
url: '/downloads',
method: 'POST',
data: {
url,
},
}).then(() => callback());
apiClient.post('/downloads', {
url,
}).then(() => callback()).catch(errCallback);
}
7 changes: 2 additions & 5 deletions uploader/client/src/components/AssetForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import AssetLiForm from "./AssetLiForm";
import {SubmissionError} from 'redux-form';
import {Translation} from "react-i18next";
import {getFormSchema} from "../requests";
import {authenticatedRequest} from "../lib/api";
import apiClient from "../lib/api";

export default class AssetForm extends Component {
static propTypes = {
Expand Down Expand Up @@ -79,10 +79,7 @@ export default class AssetForm extends Component {

let r;
try {
r = await authenticatedRequest({
url: submitPath,
data,
});
r = (await apiClient.post(submitPath, data)).data;
} catch (e) {
console.log(e);
throw new SubmissionError({_error: e.toString()});
Expand Down
4 changes: 2 additions & 2 deletions uploader/client/src/components/page/FormEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import FormPreview from "../FormPreview";
import Container from "../Container";
import {getFormSchema, getTargets} from "../../requests";
import FullPageLoader from "../FullPageLoader";
import {authenticatedRequest} from "../../lib/api";
import apiClient from "../../lib/api";

export default class FormEditor extends Component {
state = {
Expand Down Expand Up @@ -73,7 +73,7 @@ export default class FormEditor extends Component {
data.target = `/targets/${selected}`;
}

await authenticatedRequest(requestConfig);
await apiClient.request(requestConfig);

this.setState({
saved: true,
Expand Down
4 changes: 2 additions & 2 deletions uploader/client/src/components/page/TargetDataEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Button, Form} from "react-bootstrap";
import Container from "../Container";
import {getTargetParams, getTargets} from "../../requests";
import FullPageLoader from "../FullPageLoader";
import {authenticatedRequest} from "../../lib/api";
import apiClient from "../../lib/api";

export default class TargetDataEditor extends Component {
state = {
Expand Down Expand Up @@ -77,7 +77,7 @@ export default class TargetDataEditor extends Component {
data.target = `/targets/${selected}`;
}

await authenticatedRequest(requestConfig);
await apiClient.request(requestConfig);

this.setState({
saved: true,
Expand Down
22 changes: 7 additions & 15 deletions uploader/client/src/lib/api.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import axios from "axios";
import config from '../config';
import {oauthClient} from "../oauth";
import {configureClientAuthentication, createHttpClient} from "@alchemy/auth";

export const apiClient = axios.create({
baseURL: config.baseUrl,
})
const apiClient = createHttpClient(config.baseUrl);

export function authenticatedRequest(config) {
return oauthClient.wrapPromiseWithValidToken(async ({access_token, token_type}) => {
return (await apiClient.request({
...config,
headers: {
Authorization: `${token_type} ${access_token}`,
...(config.headers ?? {}),
},
})).data;
});
}
configureClientAuthentication(apiClient, oauthClient, () => {
alert('Your session has expired');
});

export default apiClient;
83 changes: 30 additions & 53 deletions uploader/client/src/multiPartUpload.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,8 @@
import {oauthClient} from "./oauth";
import {getUniqueFileId, uploadStateStorage} from "./uploadStateStorage";
import {apiClient} from "./lib/api";
import apiClient from "./lib/api";

const fileChunkSize = 5242880 // 5242880 is the minimum allowed by AWS S3;

async function asyncRequest(file, method, uri, auth, postData, onProgress, options = {}) {
const config = {
url: uri,
method,
};
if (postData) {
config.data = postData;
}

if (onProgress) {
config.onUploadProgress = onProgress;
/*{
function (axiosProgressEvent) {
loaded: number;
total?: number;
progress?: number; // in range [0..1]
bytes: number; // how many bytes have been transferred since the last trigger (delta)
estimated?: number; // estimated time in seconds
rate?: number; // upload speed in bytes
upload: true; // upload sign
}*/
}

if (file) {
file.abortController = new AbortController();
config.signal = file.abortController.signal;
}

if (auth) {
return oauthClient.wrapPromiseWithValidToken(({access_token, token_type}) => {
config.headers ??= {};
config.headers['Authorization'] = `${token_type} ${access_token}`;

return apiClient.request(config);
});
} else {
return apiClient.request(config);
}
}

export async function uploadMultipartFile(targetId, userId, file, onProgress) {
const fileUID = getUniqueFileId(file.file, fileChunkSize);

Expand All @@ -65,12 +24,16 @@ export async function uploadMultipartFile(targetId, userId, file, onProgress) {
});
}
} else {
const res = await asyncRequest(file, 'POST', `/uploads`, true, {
file.abortController = new AbortController();

const res = await apiClient.post(`/uploads`, {
filename: file.file.name,
type: file.file.type,
size: file.file.size,
}, {
signal: file.abortController.signal,
});
console.log('res', res);
console.debug('res', res);
uploadId = res.data.id;
path = res.data.path;
uploadStateStorage.initUpload(userId, fileUID, uploadId, path);
Expand All @@ -83,22 +46,32 @@ export async function uploadMultipartFile(targetId, userId, file, onProgress) {
const start = (index - 1) * fileChunkSize;
const end = (index) * fileChunkSize;

const getUploadUrlResp = await asyncRequest(file, 'POST', `/uploads/${uploadId}/part`, true, {
file.abortController = new AbortController();

const getUploadUrlResp = await apiClient.post(`/uploads/${uploadId}/part`, {
part: index,
}, {
signal: file.abortController.signal,
});
console.log('getUploadUrlResp', getUploadUrlResp);
console.debug('getUploadUrlResp', getUploadUrlResp);

const {url} = getUploadUrlResp.data;

const blob = (index < numChunks) ? file.file.slice(start, end) : file.file.slice(start);

const uploadResp = await asyncRequest(file, 'PUT', url, null, blob, (e) => {
const multiPartEvent = {
...e,
loaded: e.loaded + start,
};
file.abortController = new AbortController();

const uploadResp = await apiClient.put(url, blob, {
signal: file.abortController.signal,
anonymous: true,
onUploadProgress: (e) => {
const multiPartEvent = {
...e,
loaded: e.loaded + start,
};

onProgress(multiPartEvent);
onProgress(multiPartEvent);
}
});

const eTag = uploadResp.headers.etag;
Expand All @@ -110,12 +83,16 @@ export async function uploadMultipartFile(targetId, userId, file, onProgress) {
uploadStateStorage.updateUpload(userId, fileUID, eTag);
}

const finalRes = await asyncRequest(file, 'POST', `/assets`, true, {
file.abortController = new AbortController();

const finalRes = await apiClient.post(`/assets`, {
targetId,
multipart: {
uploadId,
parts: uploadParts,
}
}, {
signal: file.abortController.signal,
});

uploadStateStorage.removeUpload(userId, fileUID);
Expand Down
25 changes: 9 additions & 16 deletions uploader/client/src/requests.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import {authenticatedRequest} from "./lib/api";
import apiClient from "./lib/api";

export function getFormSchema(targetId) {
return authenticatedRequest({
url: `/targets/${targetId}/form-schema`,
});
export async function getFormSchema(targetId) {
return (await apiClient.get(`/targets/${targetId}/form-schema`)).data;
}

export async function getTargets() {
return (await authenticatedRequest({
url: `/targets`,
}))['hydra:member'];
return (await apiClient.get(`/targets`)).data['hydra:member'];
}

export function getTarget(id) {
return authenticatedRequest({
url: `/targets/${id}`,
});
export async function getTarget(id) {
return (await apiClient.get(`/targets/${id}`)).data;
}

export function getTargetParams(targetId) {
return authenticatedRequest({
url: `/target-params`,
export async function getTargetParams(targetId) {
return (await apiClient.get(`/target-params`, {
params: {
target: targetId,
},
});
})).data['hydra:member'];
}
8 changes: 2 additions & 6 deletions uploader/client/src/uploadBatch.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {oauthClient} from "./oauth";
import {uploadMultipartFile} from "./multiPartUpload";
import {authenticatedRequest} from "./lib/api";
import apiClient from "./lib/api";

export default class UploadBatch {
files = [];
Expand Down Expand Up @@ -127,11 +127,7 @@ export default class UploadBatch {
target: `/targets/${this.targetId}`,
};

authenticatedRequest({
url: '/commit',
method: 'POST',
data: formData,
});
apiClient.post('/commit', formData);
}

async uploadFile(index, retry = 0) {
Expand Down

0 comments on commit 7f7943a

Please sign in to comment.