web/satellite: get object map and preview by signed request.

There is a sev-2 issue to add more browser caching.
In this PR I made object map and object preview to be fetched by signed request with non-public credentials using AWS SignatureV4 package.

Change-Id: Ib5013fa6d6af3faa97eed5168c11a13f9629cd87
This commit is contained in:
Vitalii Shpital 2022-01-26 14:14:44 +02:00
parent 778e7e100d
commit 3c8e41e665
16 changed files with 596 additions and 339 deletions

View File

@ -89,7 +89,7 @@ type Config struct {
CouponCodeSignupUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account from signup" default:"false"`
FileBrowserFlowDisabled bool `help:"indicates if file browser flow is disabled" default:"false"`
CSPEnabled bool `help:"indicates if Content Security Policy is enabled" devDefault:"false" releaseDefault:"true"`
LinksharingURL string `help:"url link for linksharing requests" default:"https://link.us1.storjshare.io"`
LinksharingURL string `help:"url link for linksharing requests" default:"https://link.us1.storjshare.io" devDefault:""`
PathwayOverviewEnabled bool `help:"indicates if the overview onboarding step should render with pathways" default:"true"`
NewProjectDashboard bool `help:"indicates if new project dashboard should be used" default:"false"`
NewNavigation bool `help:"indicates if new navigation structure should be rendered" default:"true"`

View File

@ -8,6 +8,9 @@
"name": "storj-satellite",
"version": "0.1.0",
"dependencies": {
"@aws-crypto/sha256-browser": "2.0.1",
"@aws-sdk/signature-v4": "3.47.2",
"@aws-sdk/types": "3.47.1",
"apollo-cache-inmemory": "1.6.6",
"apollo-client": "2.6.10",
"apollo-link": "1.2.14",
@ -76,6 +79,162 @@
"version": "1.0.0",
"extraneous": true
},
"node_modules/@aws-crypto/ie11-detection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz",
"integrity": "sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA==",
"dependencies": {
"tslib": "^1.11.1"
}
},
"node_modules/@aws-crypto/sha256-browser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-2.0.1.tgz",
"integrity": "sha512-P4Af7E2iJqZN2HYMdWINEg++OC2CtP1ygTx6WQCzZISQA+i3Q+K3E8S8t/PSYqUnvtfh5XVjbFT9uA+4IT8C2w==",
"dependencies": {
"@aws-crypto/ie11-detection": "^2.0.0",
"@aws-crypto/sha256-js": "^2.0.1",
"@aws-crypto/supports-web-crypto": "^2.0.0",
"@aws-crypto/util": "^2.0.1",
"@aws-sdk/types": "^3.1.0",
"@aws-sdk/util-locate-window": "^3.0.0",
"@aws-sdk/util-utf8-browser": "^3.0.0",
"tslib": "^1.11.1"
}
},
"node_modules/@aws-crypto/sha256-js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-2.0.1.tgz",
"integrity": "sha512-mbHTBSPBvg6o/mN/c18Z/zifM05eJrapj5ggoOIeHIWckvkv5VgGi7r/wYpt+QAO2ySKXLNvH2d8L7bne4xrMQ==",
"dependencies": {
"@aws-crypto/util": "^2.0.1",
"@aws-sdk/types": "^3.1.0",
"tslib": "^1.11.1"
}
},
"node_modules/@aws-crypto/supports-web-crypto": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz",
"integrity": "sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA==",
"dependencies": {
"tslib": "^1.11.1"
}
},
"node_modules/@aws-crypto/util": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.1.tgz",
"integrity": "sha512-JJmFFwvbm08lULw4Nm5QOLg8+lAQeC8aCXK5xrtxntYzYXCGfHwUJ4Is3770Q7HmICsXthGQ+ZsDL7C2uH3yBQ==",
"dependencies": {
"@aws-sdk/types": "^3.1.0",
"@aws-sdk/util-utf8-browser": "^3.0.0",
"tslib": "^1.11.1"
}
},
"node_modules/@aws-sdk/is-array-buffer": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.47.1.tgz",
"integrity": "sha512-HQMvT3dP6DCjmn87WkzYxUF9RqkvuXgKfddLEKj/tg/OgDQJv9xIPjEEry8Fd36ncbBqaBmC/z2ETZhpzHQvXA==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/@aws-sdk/is-array-buffer/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@aws-sdk/signature-v4": {
"version": "3.47.2",
"resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.47.2.tgz",
"integrity": "sha512-zJIhUY8LLiQldfM9wpgVw525dHbILJovyZm3xmm6Tq/t258cawNaeOvOp9w0I3ycA3gs+nKgMXdeMjLH8QLbWg==",
"dependencies": {
"@aws-sdk/is-array-buffer": "3.47.1",
"@aws-sdk/types": "3.47.1",
"@aws-sdk/util-hex-encoding": "3.47.1",
"@aws-sdk/util-uri-escape": "3.47.1",
"tslib": "^2.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/@aws-sdk/signature-v4/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@aws-sdk/types": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.47.1.tgz",
"integrity": "sha512-c+lxJJLD5Bq8HkrgaIWQfK8oGH53CYpRRJizyQ5qfRo9aXp/qshUnIVcgnA8t0k7jfzcIfa0Q7jSSBw3EerEbg==",
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/@aws-sdk/util-hex-encoding": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.47.1.tgz",
"integrity": "sha512-9vBhp1E74s6nImK5xk7BkopQ10w6Vk8UrIinu71U7V/0PdjCEb4Jmnn++MLyim2jTT0QEGmJ6v0VjPZi9ETWaA==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/@aws-sdk/util-hex-encoding/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@aws-sdk/util-locate-window": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.47.1.tgz",
"integrity": "sha512-dMcBhtyJ7ZMNS8RS4UOVbkiR0gGrBWv+p1s9NLfMNXod9zaTAlMIKl9de8Xdshguvc8//J7heQV/7+HMvFEq2g==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/@aws-sdk/util-locate-window/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@aws-sdk/util-uri-escape": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.47.1.tgz",
"integrity": "sha512-CGqm+bT07OCJSgDo48/4Fegh9tNPR3kcOMfNWZ/J6lrt+nfAnOdXx5zZB63PjKCt5zJ7LM0thOQgAeOf2WdJzQ==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/@aws-sdk/util-uri-escape/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@aws-sdk/util-utf8-browser": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.47.1.tgz",
"integrity": "sha512-PzHEdiBhfnZbHvZ+dIlIPodDbpgrpKDYslHe9A+tH8ZfuAxxmZEqnukp7QEkFr6mBcmq3H2thcPdNT45/5pA7Q==",
"dependencies": {
"tslib": "^2.3.0"
}
},
"node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@babel/code-frame": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
@ -30543,6 +30702,156 @@
}
},
"dependencies": {
"@aws-crypto/ie11-detection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz",
"integrity": "sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA==",
"requires": {
"tslib": "^1.11.1"
}
},
"@aws-crypto/sha256-browser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-2.0.1.tgz",
"integrity": "sha512-P4Af7E2iJqZN2HYMdWINEg++OC2CtP1ygTx6WQCzZISQA+i3Q+K3E8S8t/PSYqUnvtfh5XVjbFT9uA+4IT8C2w==",
"requires": {
"@aws-crypto/ie11-detection": "^2.0.0",
"@aws-crypto/sha256-js": "^2.0.1",
"@aws-crypto/supports-web-crypto": "^2.0.0",
"@aws-crypto/util": "^2.0.1",
"@aws-sdk/types": "^3.1.0",
"@aws-sdk/util-locate-window": "^3.0.0",
"@aws-sdk/util-utf8-browser": "^3.0.0",
"tslib": "^1.11.1"
}
},
"@aws-crypto/sha256-js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-2.0.1.tgz",
"integrity": "sha512-mbHTBSPBvg6o/mN/c18Z/zifM05eJrapj5ggoOIeHIWckvkv5VgGi7r/wYpt+QAO2ySKXLNvH2d8L7bne4xrMQ==",
"requires": {
"@aws-crypto/util": "^2.0.1",
"@aws-sdk/types": "^3.1.0",
"tslib": "^1.11.1"
}
},
"@aws-crypto/supports-web-crypto": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz",
"integrity": "sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA==",
"requires": {
"tslib": "^1.11.1"
}
},
"@aws-crypto/util": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.1.tgz",
"integrity": "sha512-JJmFFwvbm08lULw4Nm5QOLg8+lAQeC8aCXK5xrtxntYzYXCGfHwUJ4Is3770Q7HmICsXthGQ+ZsDL7C2uH3yBQ==",
"requires": {
"@aws-sdk/types": "^3.1.0",
"@aws-sdk/util-utf8-browser": "^3.0.0",
"tslib": "^1.11.1"
}
},
"@aws-sdk/is-array-buffer": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.47.1.tgz",
"integrity": "sha512-HQMvT3dP6DCjmn87WkzYxUF9RqkvuXgKfddLEKj/tg/OgDQJv9xIPjEEry8Fd36ncbBqaBmC/z2ETZhpzHQvXA==",
"requires": {
"tslib": "^2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"@aws-sdk/signature-v4": {
"version": "3.47.2",
"resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.47.2.tgz",
"integrity": "sha512-zJIhUY8LLiQldfM9wpgVw525dHbILJovyZm3xmm6Tq/t258cawNaeOvOp9w0I3ycA3gs+nKgMXdeMjLH8QLbWg==",
"requires": {
"@aws-sdk/is-array-buffer": "3.47.1",
"@aws-sdk/types": "3.47.1",
"@aws-sdk/util-hex-encoding": "3.47.1",
"@aws-sdk/util-uri-escape": "3.47.1",
"tslib": "^2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"@aws-sdk/types": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.47.1.tgz",
"integrity": "sha512-c+lxJJLD5Bq8HkrgaIWQfK8oGH53CYpRRJizyQ5qfRo9aXp/qshUnIVcgnA8t0k7jfzcIfa0Q7jSSBw3EerEbg=="
},
"@aws-sdk/util-hex-encoding": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.47.1.tgz",
"integrity": "sha512-9vBhp1E74s6nImK5xk7BkopQ10w6Vk8UrIinu71U7V/0PdjCEb4Jmnn++MLyim2jTT0QEGmJ6v0VjPZi9ETWaA==",
"requires": {
"tslib": "^2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"@aws-sdk/util-locate-window": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.47.1.tgz",
"integrity": "sha512-dMcBhtyJ7ZMNS8RS4UOVbkiR0gGrBWv+p1s9NLfMNXod9zaTAlMIKl9de8Xdshguvc8//J7heQV/7+HMvFEq2g==",
"requires": {
"tslib": "^2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"@aws-sdk/util-uri-escape": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.47.1.tgz",
"integrity": "sha512-CGqm+bT07OCJSgDo48/4Fegh9tNPR3kcOMfNWZ/J6lrt+nfAnOdXx5zZB63PjKCt5zJ7LM0thOQgAeOf2WdJzQ==",
"requires": {
"tslib": "^2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"@aws-sdk/util-utf8-browser": {
"version": "3.47.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.47.1.tgz",
"integrity": "sha512-PzHEdiBhfnZbHvZ+dIlIPodDbpgrpKDYslHe9A+tH8ZfuAxxmZEqnukp7QEkFr6mBcmq3H2thcPdNT45/5pA7Q==",
"requires": {
"tslib": "^2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"@babel/code-frame": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",

View File

@ -13,6 +13,9 @@
"test": "vue-cli-service test:unit"
},
"dependencies": {
"@aws-crypto/sha256-browser": "2.0.1",
"@aws-sdk/types": "3.47.1",
"@aws-sdk/signature-v4": "3.47.2",
"apollo-cache-inmemory": "1.6.6",
"apollo-client": "2.6.10",
"apollo-link": "1.2.14",

View File

@ -8,7 +8,7 @@ import {
AccessGrantCursor,
AccessGrantsApi,
AccessGrantsPage,
GatewayCredentials,
EdgeCredentials,
} from '@/types/accessGrants';
import { HttpClient } from '@/utils/httpClient';
import { MetaUtils } from '@/utils/meta';
@ -160,7 +160,7 @@ export class AccessGrantsApiGql extends BaseGql implements AccessGrantsApi {
* @param isPublic - optional status
* @throws Error
*/
public async getGatewayCredentials(accessGrant: string, optionalURL?: string, isPublic?: boolean): Promise<GatewayCredentials> {
public async getGatewayCredentials(accessGrant: string, optionalURL?: string, isPublic?: boolean): Promise<EdgeCredentials> {
const requestURL: string = optionalURL || MetaUtils.getMetaContent('gateway-credentials-request-url');
if (!requestURL) throw new Error('Cannot get gateway credentials: request URL is not provided');
@ -176,7 +176,7 @@ export class AccessGrantsApiGql extends BaseGql implements AccessGrantsApi {
const result = await response.json();
return new GatewayCredentials(
return new EdgeCredentials(
result.id,
new Date(result.created_at),
result.access_key_id,

View File

@ -116,7 +116,7 @@ import InfoIcon from '@/../static/images/accessGrants/info.svg';
import { AnalyticsHttpApi } from '@/api/analytics';
import { RouteConfig } from '@/router';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
import { GatewayCredentials } from '@/types/accessGrants';
import { EdgeCredentials } from '@/types/accessGrants';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
// @vue/component
@ -230,7 +230,7 @@ export default class GatewayStep extends Vue {
/**
* Returns generated gateway credentials from store.
*/
public get gatewayCredentials(): GatewayCredentials {
public get gatewayCredentials(): EdgeCredentials {
return this.$store.state.accessGrantsModule.gatewayCredentials;
}

View File

@ -443,6 +443,7 @@ import FileShareModal from "./FileShareModal.vue";
import { AnalyticsHttpApi } from '@/api/analytics';
import { BrowserFile } from "@/types/browser.ts";
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { RouteConfig } from "@/router";
// @vue/component
@Component({
@ -580,18 +581,32 @@ export default class FileBrowser extends Vue {
return pathMatch;
}
/**
* Returns bucket name from store.
*/
private get bucket(): string {
return this.$store.state.objectsModule.fileComponentBucketName;
}
/**
* Returns objects flow status from store.
*/
private get isNewObjectsFlow(): string {
return this.$store.state.appStateModule.isNewObjectsFlow;
}
/**
* Return a boolean signifying whether the upload display is allowed to be shown.
*/
public get displayUpload(): boolean {
return this.fetchingFilesSpinner === false;
return !this.fetchingFilesSpinner;
}
/**
* Return a boolean signifying whether the create folder input can be shown.
*/
public get showCreateFolderInput(): boolean {
return this.$store.state.files.createFolderInputShow === true;
return this.$store.state.files.createFolderInputShow;
}
/**
@ -620,6 +635,16 @@ export default class FileBrowser extends Vue {
* Set spinner state. If routePath is not present navigate away. If there's some error re-render the page with a call to list. All of this is done on the created lifecycle method.
*/
public async created(): Promise<void> {
if (!this.bucket) {
if (this.isNewObjectsFlow) {
await this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path);
} else {
await this.$router.push(RouteConfig.Buckets.with(RouteConfig.EncryptData).path);
}
return;
}
// display the spinner while files are being fetched
this.fetchingFilesSpinner = true;

View File

@ -29,181 +29,30 @@
>
<img
v-if="previewIsImage"
ref="previewImage"
class="preview img-fluid"
:src="preSignedUrl"
src="/static/static/images/common/loader.svg"
aria-roledescription="image-preview"
>
<video
v-if="previewIsVideo"
ref="previewVideo"
class="preview"
controls
:src="preSignedUrl"
src=""
aria-roledescription="video-preview"
/>
<audio
v-if="previewIsAudio"
ref="previewAudio"
class="preview"
controls
:src="preSignedUrl"
src=""
aria-roledescription="audio-preview"
/>
<svg
v-if="placeHolderDisplayable"
width="300"
height="172"
viewBox="0 0 300 172"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="
preview-placeholder
img-fluid
"
aria-roledescription="preview-placeholder"
>
<path
d="M188.5 140C218.047 140 242 116.047 242 86.5C242 56.9528 218.047 33 188.5 33C158.953 33 135 56.9528 135 86.5C135 116.047 158.953 140 188.5 140Z"
fill="white"
/>
<path
d="M123.5 167C147.524 167 167 147.524 167 123.5C167 99.4756 147.524 80 123.5 80C99.4756 80 80 99.4756 80 123.5C80 147.524 99.4756 167 123.5 167Z"
fill="white"
/>
<path
d="M71.5 49C78.9558 49 85 42.9558 85 35.5C85 28.0442 78.9558 22 71.5 22C64.0442 22 58 28.0442 58 35.5C58 42.9558 64.0442 49 71.5 49Z"
fill="white"
/>
<path
d="M262.5 143C268.851 143 274 137.851 274 131.5C274 125.149 268.851 120 262.5 120C256.149 120 251 125.149 251 131.5C251 137.851 256.149 143 262.5 143Z"
fill="white"
/>
<path
d="M185.638 64.338L191 57M153 109L179.458 72.7948L153 109Z"
stroke="#276CFF"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M121.08 153.429L115 161M153 108L127.16 144.343L153 108Z"
stroke="#276CFF"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M134 71L115 31M152 109L139 81L152 109Z"
stroke="#FF458B"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M180.73 129.5L210 151M153 108L173.027 123.357L153 108Z"
stroke="#FF458B"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M86.7375 77.1845L72 70M152 109L109.06 88.0667L152 109Z"
stroke="#FFC600"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M152.762 109.227L244.238 76.7727"
stroke="#00E567"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M154.5 104.5L111 131"
stroke="#00E567"
stroke-width="2"
stroke-linecap="round"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M224 57H238V71H224V57Z"
fill="#00E567"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M127 2H137V12H127V2Z"
fill="#FF458B"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M150 166H156V172H150V166Z"
fill="#FF458B"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M44 0H50V6H44V0Z"
fill="#00E567"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M294 111H300V117H294V111Z"
fill="#276CFF"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 121H6V127H0V121Z"
fill="#276CFF"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M268 86H274V92H268V86Z"
fill="#FFC600"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M28 91H46V109H28V91Z"
fill="#FFC600"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M181 21H203V43H181V21Z"
fill="#276CFF"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M154.958 55L179 79.0416V136H122V55H154.958Z"
fill="#0218A7"
/>
<path
d="M146.5 80H136.5C135.119 80 134 81.1193 134 82.5C134 83.8807 135.119 85 136.5 85H146.5C147.881 85 149 83.8807 149 82.5C149 81.1193 147.881 80 146.5 80Z"
fill="white"
/>
<path
d="M164.5 92H136.5C135.119 92 134 93.1193 134 94.5C134 95.8807 135.119 97 136.5 97H164.5C165.881 97 167 95.8807 167 94.5C167 93.1193 165.881 92 164.5 92Z"
fill="white"
/>
<path
d="M164.5 104H136.5C135.119 104 134 105.119 134 106.5C134 107.881 135.119 109 136.5 109H164.5C165.881 109 167 107.881 167 106.5C167 105.119 165.881 104 164.5 104Z"
fill="white"
/>
<path
d="M164.5 116H136.5C135.119 116 134 117.119 134 118.5C134 119.881 135.119 121 136.5 121H164.5C165.881 121 167 119.881 167 118.5C167 117.119 165.881 116 164.5 116Z"
fill="white"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M154.958 79.0416V55L179 79.0416H154.958Z"
fill="#276CFF"
/>
</svg>
<PlaceholderImage v-if="placeHolderDisplayable" />
</div>
</div>
<div class="col-6 col-lg-4 pr-5">
@ -328,32 +177,11 @@
</span>
</button>
<div
v-if="objectMapIsLoading"
class="
d-flex
justify-content-center
text-primary
mt-4
"
>
<div
class="spinner-border mt-3"
role="status"
/>
</div>
<div
v-if="objectMapUrl !== null"
class="mt-5"
>
<div class="mt-5">
<div class="storage-nodes">
Nodes storing this file
</div>
<img
class="object-map"
:src="objectMapUrl"
>
<img ref="objectMap" src="/static/static/images/common/loader.svg" class="object-map" alt="object map">
</div>
</div>
</div>
@ -368,17 +196,28 @@
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import type { BrowserFile } from '@/types/browser.ts';
import { BrowserFile } from '@/types/browser.ts';
import prettyBytes from 'pretty-bytes';
import PlaceholderImage from '@/../static/images/browser/placeholder.svg'
// @vue/component
@Component
@Component({
components: {
PlaceholderImage,
}
})
export default class FileModal extends Vue {
public objectMapIsLoading = false;
public objectMapUrl = '';
public objectLink = '';
public copyText = 'Copy Link';
public $refs!: {
objectMap: HTMLImageElement;
previewImage: HTMLImageElement;
previewVideo: HTMLVideoElement;
previewAudio: HTMLAudioElement;
}
/**
* Retrieve the file object that the modal is set to from the store.
*/
@ -420,48 +259,41 @@ export default class FileModal extends Vue {
return this.filePath.split('.').pop();
}
/**
* Retrieve the presigned url from the store.
*/
public get preSignedUrl(): string {
return this.$store.getters['files/preSignedUrl'](this.filePath);
}
/**
* Check to see if the current file is an image file.
*/
public get previewIsImage(): boolean {
if (typeof this.extension === 'string') {
return ['bmp', 'svg', 'jpg', 'jpeg', 'png', 'ico', 'gif'].includes(
this.extension.toLowerCase()
);
if (typeof this.extension !== 'string') {
return false;
}
return false;
return ['bmp', 'svg', 'jpg', 'jpeg', 'png', 'ico', 'gif'].includes(
this.extension.toLowerCase()
);
}
/**
* Check to see if the current file is a video file.
*/
public get previewIsVideo(): boolean {
if (typeof this.extension === 'string') {
return ['m4v', 'mp4', 'webm', 'mov', 'mkv'].includes(
this.extension.toLowerCase()
);
if (typeof this.extension !== 'string') {
return false;
}
return false;
return ['m4v', 'mp4', 'webm', 'mov', 'mkv'].includes(
this.extension.toLowerCase()
);
}
/**
* Check to see if the current file is an audio file.
*/
public get previewIsAudio(): boolean {
if (typeof this.extension === 'string') {
return ['mp3', 'wav', 'ogg'].includes(this.extension.toLowerCase());
if (typeof this.extension !== 'string') {
return false;
}
return false;
return ['mp3', 'wav', 'ogg'].includes(this.extension.toLowerCase());
}
/**
@ -472,14 +304,7 @@ export default class FileModal extends Vue {
this.previewIsImage,
this.previewIsVideo,
this.previewIsAudio
].every((value) => !!value === false);
}
/**
* Check to see if the object map exists.
*/
private get objectMapUrlExists(): boolean {
return this.objectMapUrl !== null;
].every((value) => !value);
}
/**
@ -487,33 +312,39 @@ export default class FileModal extends Vue {
*/
@Watch("filePath")
private handleFilePathChange() {
this.fetchObjectMapUrl();
this.fetchObjectMap();
if (!this.placeHolderDisplayable) this.setPreview();
}
/**
* Call `fetchObjectMapUrl` on the created lifecycle method.
* Call `fetchObjectMapUrl` on the mounted lifecycle method.
*/
public created(): void {
this.fetchObjectMapUrl();
public mounted(): void {
this.fetchObjectMap();
if (!this.placeHolderDisplayable) this.setPreview();
}
/**
* Get the object map url for the file being displayed.
* Get the object map for the file being displayed.
*/
private async fetchObjectMapUrl(): Promise<void> {
this.objectMapIsLoading = true;
const objectMapUrl: string = await this.$store.state.files.fetchObjectMapUrl(
this.filePath
);
private async fetchObjectMap(): Promise<void> {
try {
if (!this.$store.state.files.fetchObjectMap) {
return;
}
await new Promise((resolve) => {
const preload = new Image();
preload.onload = resolve;
preload.src = objectMapUrl;
});
const objectMap: Blob | null = await this.$store.state.files.fetchObjectMap(
this.filePath
);
this.objectMapUrl = objectMapUrl;
this.objectMapIsLoading = false;
if (!objectMap) {
return;
}
this.$refs.objectMap.src = URL.createObjectURL(objectMap);
} catch (error) {
await this.$notify.error(error.message);
}
}
/**
@ -523,6 +354,40 @@ export default class FileModal extends Vue {
this.$store.dispatch('files/download', this.file);
}
/**
* Set preview object.
*/
public async setPreview(): Promise<void> {
try {
if (!this.$store.state.files.fetchObjectPreview) {
return;
}
const object: Blob | null = await this.$store.state.files.fetchObjectPreview(
this.filePath
);
if (!object) {
return;
}
const objectURL = URL.createObjectURL(object);
switch (true) {
case this.previewIsImage:
this.$refs.previewImage.src = objectURL;
break;
case this.previewIsVideo:
this.$refs.previewVideo.src = objectURL;
break;
case this.previewIsAudio:
this.$refs.previewAudio.src = objectURL;
}
} catch (error) {
await this.$notify.error(error.message);
}
}
/**
* Close the current opened file.
*/
@ -606,18 +471,15 @@ export default class FileModal extends Vue {
max-width: 100%;
position: relative;
font-size: 18px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.preview {
width: 100%;
}
.preview-placeholder {
background: #f9fafc;
width: 100%;
height: 100%;
}
.object-map {
width: 100%;
}

View File

@ -71,7 +71,7 @@ import BucketIcon from '@/../static/images/objects/bucket.svg';
import { RouteConfig } from '@/router';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
import { DEMO_BUCKET_NAME, OBJECTS_ACTIONS } from '@/store/modules/objects';
import { AccessGrant, GatewayCredentials } from '@/types/accessGrants';
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
import { MetaUtils } from '@/utils/meta';
import { Validator } from '@/utils/validation';
@ -187,7 +187,7 @@ export default class BucketsView extends Vue {
const accessGrant = accessGrantEvent.data.value;
const gatewayCredentials: GatewayCredentials = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant});
const gatewayCredentials: EdgeCredentials = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant, isPublic: false});
await this.$store.dispatch(OBJECTS_ACTIONS.SET_GATEWAY_CREDENTIALS, gatewayCredentials);
await this.$store.dispatch(OBJECTS_ACTIONS.SET_S3_CLIENT);
}

View File

@ -64,7 +64,7 @@ import pbkdf2 from 'pbkdf2';
import { RouteConfig } from '@/router';
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
import { LocalData } from "@/utils/localData";
import { GatewayCredentials } from "@/types/accessGrants";
import { EdgeCredentials } from "@/types/accessGrants";
import { ACCESS_GRANTS_ACTIONS } from "@/store/modules/accessGrants";
import { APP_STATE_MUTATIONS } from "@/store/mutationConstants";
import { MetaUtils } from "@/utils/meta";
@ -211,7 +211,7 @@ export default class EncryptData extends Vue {
const accessGrant = accessGrantEvent.data.value;
const gatewayCredentials: GatewayCredentials = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant});
const gatewayCredentials: EdgeCredentials = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant});
await this.$store.dispatch(OBJECTS_ACTIONS.SET_GATEWAY_CREDENTIALS, gatewayCredentials);
}

View File

@ -13,6 +13,9 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { SignatureV4 } from "@aws-sdk/signature-v4";
import { Sha256 } from "@aws-crypto/sha256-browser";
import { HttpRequest, Credentials } from "@aws-sdk/types";
import UploadCancelPopup from '@/components/objects/UploadCancelPopup.vue';
import FileBrowser from '@/components/browser/FileBrowser.vue';
@ -20,7 +23,7 @@ import FileBrowser from '@/components/browser/FileBrowser.vue';
import { AnalyticsHttpApi } from '@/api/analytics';
import { RouteConfig } from '@/router';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
import { AccessGrant, GatewayCredentials } from '@/types/accessGrants';
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { MetaUtils } from '@/utils/meta';
@ -32,44 +35,31 @@ import { MetaUtils } from '@/utils/meta';
},
})
export default class UploadFile extends Vue {
private credentials: EdgeCredentials;
private linksharingURL = '';
private worker: Worker;
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
/**
* Lifecycle hook after initial render.
* Checks if bucket is chosen.
* Sets local worker.
*/
public mounted(): void {
if (!this.bucket) {
if (this.isNewObjectsFlow) {
this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path);
} else {
this.$router.push(RouteConfig.Buckets.with(RouteConfig.EncryptData).path);
}
return;
}
this.linksharingURL = MetaUtils.getMetaContent('linksharing-url');
this.setWorker();
}
/**
* Lifecycle hook after vue instance was created.
* Initiates file browser.
*/
public created(): void {
this.linksharingURL = MetaUtils.getMetaContent('linksharing-url');
this.setWorker();
this.credentials = this.$store.state.objectsModule.gatewayCredentials;
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,
endpoint: this.credentials.endpoint,
accessKey: this.credentials.accessKeyId,
secretKey: this.credentials.secretKey,
bucket: this.bucket,
browserRoot: RouteConfig.Buckets.with(RouteConfig.UploadFile).path,
fetchObjectMapUrl: async (path: string) => await this.generateObjectMapUrl(path),
fetchSharedLink: async (path: string) => await this.generateShareLinkUrl(path),
fetchObjectMap: this.fetchObjectMap,
fetchObjectPreview: this.fetchObjectPreview,
fetchSharedLink: this.generateShareLinkUrl,
});
}
@ -83,20 +73,15 @@ export default class UploadFile extends Vue {
/**
* Generates a URL for an object map.
*/
public async generateObjectMapUrl(path: string): Promise<string> {
path = `${this.bucket}/${path}`;
public async fetchObjectMap(path: string): Promise<Blob | null> {
return await this.getObjectViewOrMapBySignedRequest(path, true)
}
try {
const key: string = await this.accessKey(this.apiKey, path);
path = encodeURIComponent(path.trim());
return `${this.linksharingURL}/s/${key}/${path}?map=1`;
} catch (error) {
await this.$notify.error(error.message);
return '';
}
/**
* Generates a URL for an object map.
*/
public async fetchObjectPreview(path: string): Promise<Blob | null> {
return await this.getObjectViewOrMapBySignedRequest(path, false)
}
/**
@ -109,13 +94,13 @@ export default class UploadFile extends Vue {
const cleanAPIKey: AccessGrant = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, LINK_SHARING_AG_NAME);
try {
const key: string = await this.accessKey(cleanAPIKey.secret, path);
const credentials: EdgeCredentials = await this.generateCredentials(cleanAPIKey.secret, path, true);
path = encodeURIComponent(path.trim());
await this.analytics.eventTriggered(AnalyticsEvent.LINK_SHARED);
return `${this.linksharingURL}/${key}/${path}`;
return `${this.linksharingURL}/${credentials.accessKeyId}/${path}`;
} catch (error) {
await this.$notify.error(error.message);
@ -134,9 +119,74 @@ export default class UploadFile extends Vue {
}
/**
* Generates public access key.
* Returns a URL for an object or a map.
*/
private async accessKey(cleanApiKey: string, path: string): Promise<string> {
private async getObjectViewOrMapBySignedRequest(path: string, isMap: boolean): Promise<Blob | null> {
try {
path = `${this.bucket}/${path}`;
path = encodeURIComponent(path.trim());
const url = new URL(`${this.linksharingURL}/s/${this.credentials.accessKeyId}/${path}`)
let request: HttpRequest = {
method: 'GET',
protocol: url.protocol,
hostname: url.hostname,
port: parseFloat(url.port),
path: url.pathname,
headers: {
'host': url.host,
}
}
if (isMap) {
request = Object.assign(request, {query: { 'map': '1' }});
} else {
request = Object.assign(request, {query: { 'view': '1' }});
}
const signerCredentials: Credentials = {
accessKeyId: this.credentials.accessKeyId,
secretAccessKey: this.credentials.secretKey,
};
const signer = new SignatureV4({
applyChecksum: true,
uriEscapePath: false,
credentials: signerCredentials,
region: "eu1",
service: "linksharing",
sha256: Sha256,
});
const signedRequest: HttpRequest = await signer.sign(request);
let requestURL = `${this.linksharingURL}${signedRequest.path}`;
if (isMap) {
requestURL = `${requestURL}?map=1`;
} else {
requestURL = `${requestURL}?view=1`;
}
const response = await fetch(requestURL, signedRequest);
if (response.ok) {
return await response.blob();
}
await this.$notify.error(`${response.status}. Failed to fetch object view or map`);
return null;
} catch (error) {
await this.$notify.error(error.message);
return null;
}
}
/**
* Generates gateway credentials.
*/
private async generateCredentials(cleanApiKey: string, path: string, isPublic: boolean): Promise<EdgeCredentials> {
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
this.worker.postMessage({
@ -152,7 +202,7 @@ export default class UploadFile extends Vue {
if (grantData.error) {
await this.$notify.error(grantData.error);
return '';
return new EdgeCredentials();
}
this.worker.postMessage({
@ -170,12 +220,10 @@ export default class UploadFile extends Vue {
if (data.error) {
await this.$notify.error(data.error);
return '';
return new EdgeCredentials();
}
const gatewayCredentials: GatewayCredentials = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant: data.value, isPublic: true});
return gatewayCredentials.accessKeyId;
return await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.GET_GATEWAY_CREDENTIALS, {accessGrant: data.value, isPublic});
}
/**
@ -185,13 +233,6 @@ export default class UploadFile extends Vue {
return this.$store.state.appStateModule.appState.isUploadCancelPopupVisible;
}
/**
* Returns objects flow status from store.
*/
private get isNewObjectsFlow(): string {
return this.$store.state.appStateModule.isNewObjectsFlow;
}
/**
* Returns passphrase from store.
*/
@ -199,13 +240,6 @@ export default class UploadFile extends Vue {
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.
*/

View File

@ -9,7 +9,7 @@ import {
AccessGrantsOrderBy,
AccessGrantsPage,
DurationPermission,
GatewayCredentials,
EdgeCredentials,
} from '@/types/accessGrants';
import { SortDirection } from '@/types/common';
@ -82,7 +82,7 @@ export class AccessGrantsState {
public isUpload = true;
public isList = true;
public isDelete = true;
public gatewayCredentials: GatewayCredentials = new GatewayCredentials();
public gatewayCredentials: EdgeCredentials = new EdgeCredentials();
public accessGrantsWebWorker: Worker | null = null;
public isAccessGrantsWebWorkerReady = false;
}
@ -125,7 +125,7 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
return accessGrant;
});
},
[SET_GATEWAY_CREDENTIALS](state: AccessGrantsState, credentials: GatewayCredentials) {
[SET_GATEWAY_CREDENTIALS](state: AccessGrantsState, credentials: EdgeCredentials) {
state.gatewayCredentials = credentials;
},
[SET_PAGE_NUMBER](state: AccessGrantsState, pageNumber: number) {
@ -204,7 +204,7 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
state.selectedBucketNames = [];
state.permissionNotBefore = null;
state.permissionNotAfter = null;
state.gatewayCredentials = new GatewayCredentials();
state.gatewayCredentials = new EdgeCredentials();
},
},
actions: {
@ -248,8 +248,8 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
deleteAccessGrantsByNameAndProjectID: async function({rootGetters}: AccessGrantsContext, name: string): Promise<void> {
await api.deleteByNameAndProjectID(name, rootGetters.selectedProject.id);
},
getGatewayCredentials: async function({commit}: AccessGrantsContext, payload): Promise<GatewayCredentials> {
const credentials: GatewayCredentials = await api.getGatewayCredentials(payload.accessGrant, payload.optionalURL, payload.isPublic);
getGatewayCredentials: async function({commit}: AccessGrantsContext, payload): Promise<EdgeCredentials> {
const credentials: EdgeCredentials = await api.getGatewayCredentials(payload.accessGrant, payload.optionalURL, payload.isPublic);
commit(SET_GATEWAY_CREDENTIALS, credentials);

View File

@ -31,7 +31,8 @@ export default {
shiftSelectedFiles: [],
filesToBeDeleted: [],
fetchSharedLink: null,
fetchObjectMapUrl: null,
fetchObjectMap: null,
fetchObjectPreview: null,
openedDropdown: null,
headingSorted: "name",
orderBy: "asc",
@ -70,13 +71,6 @@ export default {
return groupedFiles;
},
preSignedUrl: (state) => (url) => {
return state.s3.getSignedUrl("getObject", {
Bucket: state.bucket,
Key: url
});
},
isInitialized: (state) => state.s3 !== null
},
mutations: {
@ -90,7 +84,8 @@ export default {
browserRoot,
openModalOnFirstUpload = true,
fetchSharedLink = () => "javascript:null",
fetchObjectMapUrl = () =>
fetchObjectPreview = () => "javascript:null",
fetchObjectMap = () =>
new Promise((resolve) =>
setTimeout(
() =>
@ -118,7 +113,8 @@ export default {
state.browserRoot = browserRoot;
state.openModalOnFirstUpload = openModalOnFirstUpload;
state.fetchSharedLink = fetchSharedLink;
state.fetchObjectMapUrl = fetchObjectMapUrl;
state.fetchObjectMap = fetchObjectMap;
state.fetchObjectPreview = fetchObjectPreview;
state.path = "";
},

View File

@ -4,7 +4,7 @@
import S3, { Bucket } from 'aws-sdk/clients/s3';
import { StoreModule } from '@/store';
import { GatewayCredentials } from '@/types/accessGrants';
import { EdgeCredentials } from '@/types/accessGrants';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
export const OBJECTS_ACTIONS = {
@ -47,7 +47,7 @@ const {
export class ObjectsState {
public apiKey = '';
public gatewayCredentials: GatewayCredentials = new GatewayCredentials();
public gatewayCredentials: EdgeCredentials = new EdgeCredentials();
public s3Client: S3 = new S3({
s3ForcePathStyle: true,
signatureVersion: "v4",
@ -80,7 +80,7 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
[SET_API_KEY](state: ObjectsState, apiKey: string) {
state.apiKey = apiKey;
},
[SET_GATEWAY_CREDENTIALS](state: ObjectsState, credentials: GatewayCredentials) {
[SET_GATEWAY_CREDENTIALS](state: ObjectsState, credentials: EdgeCredentials) {
state.gatewayCredentials = credentials;
},
[SET_S3_CLIENT](state: ObjectsState) {
@ -110,7 +110,7 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
[CLEAR](state: ObjectsState) {
state.apiKey = '';
state.passphrase = '';
state.gatewayCredentials = new GatewayCredentials();
state.gatewayCredentials = new EdgeCredentials();
state.s3Client = new S3({
s3ForcePathStyle: true,
signatureVersion: "v4",
@ -124,7 +124,7 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
setApiKey: function({commit}: ObjectsContext, apiKey: string): void {
commit(SET_API_KEY, apiKey);
},
setGatewayCredentials: function({commit}: ObjectsContext, credentials: GatewayCredentials): void {
setGatewayCredentials: function({commit}: ObjectsContext, credentials: EdgeCredentials): void {
commit(SET_GATEWAY_CREDENTIALS, credentials);
},
setS3Client: function({commit}: ObjectsContext): void {

View File

@ -44,10 +44,10 @@ export interface AccessGrantsApi {
/**
* Get gateway credentials using access grant
*
* @returns GatewayCredentials
* @returns EdgeCredentials
* @throws Error
*/
getGatewayCredentials(accessGrant: string, optionalURL?: string, isPublic?: boolean): Promise<GatewayCredentials>;
getGatewayCredentials(accessGrant: string, optionalURL?: string, isPublic?: boolean): Promise<EdgeCredentials>;
}
/**
@ -121,9 +121,9 @@ export class DurationPermission {
}
/**
* GatewayCredentials class holds info for gateway credentials generated from access grant.
* EdgeCredentials class holds info for edge credentials generated from access grant.
*/
export class GatewayCredentials {
export class EdgeCredentials {
constructor(
public id: string = '',
public createdAt: Date = new Date(),

View File

@ -0,0 +1,28 @@
<svg width="100%" height="100%" viewBox="0 0 300 172" fill="none" xmlns="http://www.w3.org/2000/svg" class="img-fluid" aria-roledescription="preview-placeholder">
<path d="M188.5 140C218.047 140 242 116.047 242 86.5C242 56.9528 218.047 33 188.5 33C158.953 33 135 56.9528 135 86.5C135 116.047 158.953 140 188.5 140Z" fill="white"/>
<path d="M123.5 167C147.524 167 167 147.524 167 123.5C167 99.4756 147.524 80 123.5 80C99.4756 80 80 99.4756 80 123.5C80 147.524 99.4756 167 123.5 167Z" fill="white"/>
<path d="M71.5 49C78.9558 49 85 42.9558 85 35.5C85 28.0442 78.9558 22 71.5 22C64.0442 22 58 28.0442 58 35.5C58 42.9558 64.0442 49 71.5 49Z" fill="white"/>
<path d="M262.5 143C268.851 143 274 137.851 274 131.5C274 125.149 268.851 120 262.5 120C256.149 120 251 125.149 251 131.5C251 137.851 256.149 143 262.5 143Z" fill="white"/>
<path d="M185.638 64.338L191 57M153 109L179.458 72.7948L153 109Z" stroke="#276CFF" stroke-width="2" stroke-linecap="round"/>
<path d="M121.08 153.429L115 161M153 108L127.16 144.343L153 108Z" stroke="#276CFF" stroke-width="2" stroke-linecap="round"/>
<path d="M134 71L115 31M152 109L139 81L152 109Z" stroke="#FF458B" stroke-width="2" stroke-linecap="round"/>
<path d="M180.73 129.5L210 151M153 108L173.027 123.357L153 108Z" stroke="#FF458B" stroke-width="2" stroke-linecap="round"/>
<path d="M86.7375 77.1845L72 70M152 109L109.06 88.0667L152 109Z" stroke="#FFC600" stroke-width="2" stroke-linecap="round"/>
<path d="M152.762 109.227L244.238 76.7727" stroke="#00E567" stroke-width="2" stroke-linecap="round"/>
<path d="M154.5 104.5L111 131" stroke="#00E567" stroke-width="2" stroke-linecap="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M224 57H238V71H224V57Z" fill="#00E567"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M127 2H137V12H127V2Z" fill="#FF458B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M150 166H156V172H150V166Z" fill="#FF458B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M44 0H50V6H44V0Z" fill="#00E567"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M294 111H300V117H294V111Z" fill="#276CFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 121H6V127H0V121Z" fill="#276CFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M268 86H274V92H268V86Z" fill="#FFC600"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 91H46V109H28V91Z" fill="#FFC600"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M181 21H203V43H181V21Z" fill="#276CFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M154.958 55L179 79.0416V136H122V55H154.958Z" fill="#0218A7"/>
<path d="M146.5 80H136.5C135.119 80 134 81.1193 134 82.5C134 83.8807 135.119 85 136.5 85H146.5C147.881 85 149 83.8807 149 82.5C149 81.1193 147.881 80 146.5 80Z" fill="white"/>
<path d="M164.5 92H136.5C135.119 92 134 93.1193 134 94.5C134 95.8807 135.119 97 136.5 97H164.5C165.881 97 167 95.8807 167 94.5C167 93.1193 165.881 92 164.5 92Z" fill="white"/>
<path d="M164.5 104H136.5C135.119 104 134 105.119 134 106.5C134 107.881 135.119 109 136.5 109H164.5C165.881 109 167 107.881 167 106.5C167 105.119 165.881 104 164.5 104Z" fill="white"/>
<path d="M164.5 116H136.5C135.119 116 134 117.119 134 118.5C134 119.881 135.119 121 136.5 121H164.5C165.881 121 167 119.881 167 118.5C167 117.119 165.881 116 164.5 116Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M154.958 79.0416V55L179 79.0416H154.958Z" fill="#276CFF"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -6,7 +6,7 @@ import {
AccessGrantCursor,
AccessGrantsApi,
AccessGrantsPage,
GatewayCredentials,
EdgeCredentials,
} from '@/types/accessGrants';
/**
@ -36,7 +36,7 @@ export class AccessGrantsMock implements AccessGrantsApi {
return Promise.resolve();
}
getGatewayCredentials(_accessGrant: string, _optionalURL?: string): Promise<GatewayCredentials> {
return Promise.resolve(new GatewayCredentials('testCredId', new Date(), 'testAccessKeyId', 'testSecret', 'testEndpoint'));
getGatewayCredentials(_accessGrant: string, _optionalURL?: string): Promise<EdgeCredentials> {
return Promise.resolve(new EdgeCredentials('testCredId', new Date(), 'testAccessKeyId', 'testSecret', 'testEndpoint'));
}
}