2021-02-22 16:46:07 +00:00
|
|
|
// Copyright (C) 2021 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2021-03-23 20:50:34 +00:00
|
|
|
<template>
|
2021-04-14 21:28:48 +01:00
|
|
|
<div>
|
2021-08-10 14:14:37 +01:00
|
|
|
<p class="back" @click="goToBuckets"><- Back to Buckets</p>
|
2021-04-14 21:28:48 +01:00
|
|
|
<div class="file-browser">
|
2021-08-10 14:14:37 +01:00
|
|
|
<FileBrowser />
|
2021-04-14 21:28:48 +01:00
|
|
|
</div>
|
2021-08-10 14:14:37 +01:00
|
|
|
<UploadCancelPopup v-if="isCancelUploadPopupVisible" />
|
2021-03-23 20:50:34 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2021-02-22 16:46:07 +00:00
|
|
|
<script lang="ts">
|
2021-03-23 20:50:34 +00:00
|
|
|
import { FileBrowser } from 'browser';
|
2021-02-22 16:46:07 +00:00
|
|
|
import { Component, Vue } from 'vue-property-decorator';
|
|
|
|
|
2021-06-18 15:00:12 +01:00
|
|
|
import UploadCancelPopup from '@/components/objects/UploadCancelPopup.vue';
|
|
|
|
|
2021-06-03 21:59:31 +01:00
|
|
|
import { AnalyticsHttpApi } from '@/api/analytics';
|
2021-03-23 20:50:34 +00:00
|
|
|
import { RouteConfig } from '@/router';
|
|
|
|
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
|
|
|
import { AccessGrant, GatewayCredentials } from '@/types/accessGrants';
|
2021-06-01 22:44:37 +01:00
|
|
|
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
2021-06-03 21:59:31 +01:00
|
|
|
import { MetaUtils } from '@/utils/meta';
|
2021-06-01 22:44:37 +01:00
|
|
|
|
2021-03-23 20:50:34 +00:00
|
|
|
@Component({
|
|
|
|
components: {
|
|
|
|
FileBrowser,
|
2021-06-18 15:00:12 +01:00
|
|
|
UploadCancelPopup,
|
2021-03-23 20:50:34 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
export default class UploadFile extends Vue {
|
2021-04-09 12:56:21 +01:00
|
|
|
private linksharingURL = '';
|
2021-03-23 20:50:34 +00:00
|
|
|
private worker: Worker;
|
2021-06-01 22:44:37 +01:00
|
|
|
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
2021-03-23 20:50:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Lifecycle hook after initial render.
|
|
|
|
* Checks if bucket is chosen.
|
|
|
|
* Sets local worker.
|
|
|
|
*/
|
|
|
|
public mounted(): void {
|
|
|
|
if (!this.bucket) {
|
2021-08-16 12:02:40 +01:00
|
|
|
this.$router.push(RouteConfig.Objects.with(RouteConfig.EncryptData).path);
|
2021-03-23 20:50:34 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-09 12:56:21 +01:00
|
|
|
this.linksharingURL = MetaUtils.getMetaContent('linksharing-url');
|
|
|
|
|
2021-03-23 20:50:34 +00:00
|
|
|
this.setWorker();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lifecycle hook after vue instance was created.
|
|
|
|
* Initiates file browser.
|
|
|
|
*/
|
|
|
|
public created(): void {
|
|
|
|
this.$store.commit('files/init', {
|
|
|
|
endpoint: this.$store.state.objectsModule.gatewayCredentials.endpoint,
|
|
|
|
accessKey: this.$store.state.objectsModule.gatewayCredentials.accessKeyId,
|
|
|
|
secretKey: this.$store.state.objectsModule.gatewayCredentials.secretKey,
|
|
|
|
bucket: this.bucket,
|
|
|
|
browserRoot: RouteConfig.Objects.with(RouteConfig.UploadFile).path,
|
|
|
|
getObjectMapUrl: async (path: string) => await this.generateObjectMapUrl(path),
|
|
|
|
getSharedLink: async (path: string) => await this.generateShareLinkUrl(path),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-04-14 21:28:48 +01:00
|
|
|
/**
|
|
|
|
* Redirects to buckets list view.
|
|
|
|
*/
|
|
|
|
public goToBuckets(): void {
|
|
|
|
this.$router.push(RouteConfig.Objects.with(RouteConfig.BucketsManagement).path);
|
|
|
|
}
|
|
|
|
|
2021-03-23 20:50:34 +00:00
|
|
|
/**
|
|
|
|
* Generates a URL for an object map.
|
|
|
|
*/
|
|
|
|
public async generateObjectMapUrl(path: string): Promise<string> {
|
|
|
|
path = `${this.bucket}/${path}`;
|
|
|
|
|
|
|
|
try {
|
2021-05-24 15:28:29 +01:00
|
|
|
const key: string = await this.accessKey(this.apiKey, path);
|
2021-03-23 20:50:34 +00:00
|
|
|
|
2021-04-15 17:23:55 +01:00
|
|
|
path = encodeURIComponent(path.trim());
|
|
|
|
|
2021-04-09 12:56:21 +01:00
|
|
|
return `${this.linksharingURL}/s/${key}/${path}?map=1`;
|
2021-03-23 20:50:34 +00:00
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(error.message);
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a URL for a link sharing service.
|
|
|
|
*/
|
|
|
|
public async generateShareLinkUrl(path: string): Promise<string> {
|
|
|
|
path = `${this.bucket}/${path}`;
|
|
|
|
const now = new Date();
|
|
|
|
const LINK_SHARING_AG_NAME = `${path}_shared-object_${now.toISOString()}`;
|
|
|
|
const cleanAPIKey: AccessGrant = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, LINK_SHARING_AG_NAME);
|
|
|
|
|
|
|
|
try {
|
2021-05-24 15:28:29 +01:00
|
|
|
const key: string = await this.accessKey(cleanAPIKey.secret, path);
|
2021-03-23 20:50:34 +00:00
|
|
|
|
2021-04-15 17:23:55 +01:00
|
|
|
path = encodeURIComponent(path.trim());
|
|
|
|
|
2021-06-01 22:44:37 +01:00
|
|
|
await this.analytics.eventTriggered(AnalyticsEvent.LINK_SHARED);
|
|
|
|
|
2021-04-09 12:56:21 +01:00
|
|
|
return `${this.linksharingURL}/${key}/${path}`;
|
2021-03-23 20:50:34 +00:00
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(error.message);
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets local worker with worker instantiated in store.
|
|
|
|
*/
|
|
|
|
public setWorker(): void {
|
|
|
|
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
|
|
|
this.worker.onerror = (error: ErrorEvent) => {
|
|
|
|
this.$notify.error(error.message);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-06-18 15:00:12 +01:00
|
|
|
/**
|
|
|
|
* Indicates if upload cancel popup is visible.
|
|
|
|
*/
|
|
|
|
public get isCancelUploadPopupVisible(): boolean {
|
|
|
|
return this.$store.state.appStateModule.appState.isUploadCancelPopupVisible;
|
|
|
|
}
|
|
|
|
|
2021-03-23 20:50:34 +00:00
|
|
|
/**
|
|
|
|
* Generates public access key.
|
|
|
|
*/
|
2021-05-24 15:28:29 +01:00
|
|
|
private async accessKey(cleanApiKey: string, path: string): Promise<string> {
|
2021-03-23 20:50:34 +00:00
|
|
|
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
|
|
|
|
|
|
|
|
this.worker.postMessage({
|
|
|
|
'type': 'GenerateAccess',
|
|
|
|
'apiKey': cleanApiKey,
|
|
|
|
'passphrase': this.passphrase,
|
|
|
|
'projectID': this.$store.getters.selectedProject.id,
|
|
|
|
'satelliteNodeURL': satelliteNodeURL,
|
|
|
|
});
|
|
|
|
|
|
|
|
const grantEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
|
|
|
const grantData = grantEvent.data;
|
|
|
|
if (grantData.error) {
|
|
|
|
await this.$notify.error(grantData.error);
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
this.worker.postMessage({
|
|
|
|
'type': 'RestrictGrant',
|
|
|
|
'isDownload': true,
|
|
|
|
'isUpload': true,
|
|
|
|
'isList': true,
|
|
|
|
'isDelete': true,
|
|
|
|
'paths': [path],
|
|
|
|
'grant': grantData.value,
|
|
|
|
});
|
|
|
|
|
|
|
|
const event: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
|
|
|
const data = event.data;
|
|
|
|
if (data.error) {
|
|
|
|
await this.$notify.error(data.error);
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
const gatewayCredentials: GatewayCredentials = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant: data.value, isPublic: true});
|
|
|
|
|
|
|
|
return gatewayCredentials.accessKeyId;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns passphrase from store.
|
|
|
|
*/
|
|
|
|
private get passphrase(): string {
|
|
|
|
return this.$store.state.objectsModule.passphrase;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns apiKey from store.
|
|
|
|
*/
|
|
|
|
private get apiKey(): string {
|
|
|
|
return this.$store.state.objectsModule.apiKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns bucket name from store.
|
|
|
|
*/
|
|
|
|
private get bucket(): string {
|
|
|
|
return this.$store.state.objectsModule.fileComponentBucketName;
|
|
|
|
}
|
|
|
|
}
|
2021-02-22 16:46:07 +00:00
|
|
|
</script>
|
2021-03-23 20:50:34 +00:00
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
@import '../../../node_modules/browser/dist/browser.css';
|
|
|
|
|
2021-04-14 21:28:48 +01:00
|
|
|
.back {
|
|
|
|
font-family: 'font_medium', sans-serif;
|
|
|
|
color: #000;
|
|
|
|
font-size: 20px;
|
|
|
|
cursor: pointer;
|
|
|
|
margin: 0 0 30px 15px;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
|
|
|
|
.back:hover {
|
|
|
|
color: #007bff;
|
|
|
|
text-decoration: underline;
|
|
|
|
}
|
|
|
|
|
2021-03-23 20:50:34 +00:00
|
|
|
.file-browser {
|
|
|
|
font-family: 'font_regular', sans-serif;
|
|
|
|
padding-bottom: 200px;
|
|
|
|
}
|
|
|
|
</style>
|