web/satellite: initial setup of bucket's view of objects page
WHAT: setup of objects store module, setup of initial bucket's view, generate special API key that will be used to generate gateway credentials WHY: initial setup of future bucket's management view Change-Id: I0078869b95c04c0b142b2e112e93ff2332e8e90f
This commit is contained in:
parent
8e1aa4bb74
commit
6ddcacbe78
@ -46,6 +46,8 @@ export default class AccountDropdown extends Vue {
|
||||
* Performs logout on backend than clears all user information from store and local storage.
|
||||
*/
|
||||
public async onLogoutClick(): Promise<void> {
|
||||
await this.$router.push(RouteConfig.Login.path);
|
||||
|
||||
try {
|
||||
await this.auth.logout();
|
||||
} catch (error) {
|
||||
@ -54,7 +56,6 @@ export default class AccountDropdown extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.$router.push(RouteConfig.Login.path);
|
||||
await this.$store.dispatch(PM_ACTIONS.CLEAR);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.CLEAR);
|
||||
await this.$store.dispatch(USER_ACTIONS.CLEAR);
|
||||
|
98
web/satellite/src/components/objects/BucketsView.vue
Normal file
98
web/satellite/src/components/objects/BucketsView.vue
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="buckets-view">
|
||||
<div class="buckets-view__title-area">
|
||||
<h1 class="buckets-view__title-area__title">Buckets</h1>
|
||||
</div>
|
||||
<div class="buckets-view__loader" v-if="isLoading"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
|
||||
|
||||
@Component
|
||||
export default class BucketsView extends Vue {
|
||||
private readonly FILE_BROWSER_AG_NAME: string = 'Web file browser API key';
|
||||
|
||||
public isLoading: boolean = true;
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Setup gateway credentials.
|
||||
*/
|
||||
public async mounted(): Promise<void> {
|
||||
if (!this.$route.params.passphrase) {
|
||||
await this.$router.push(RouteConfig.Objects.path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const accessGrant = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, this.FILE_BROWSER_AG_NAME);
|
||||
await this.$store.dispatch(OBJECTS_ACTIONS.SET_ACCESS_GRANT, accessGrant);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook before component destroying.
|
||||
* Remove temporary created access grant.
|
||||
*/
|
||||
public async beforeDestroy(): Promise<void> {
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.DELETE_BY_NAME_AND_PROJECT_ID, this.FILE_BROWSER_AG_NAME);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.buckets-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
&__title-area {
|
||||
margin-bottom: 100px;
|
||||
width: 100%;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
color: #232b34;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
&__loader {
|
||||
border: 16px solid #f3f3f3;
|
||||
border-top: 16px solid #3498db;
|
||||
border-radius: 50%;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
@ -3,11 +3,14 @@
|
||||
|
||||
<template>
|
||||
<div class="create-pass">
|
||||
<GeneratePassphrase
|
||||
:is-loading="isLoading"
|
||||
:on-button-click="onNextClick"
|
||||
:set-parent-passphrase="setPassphrase"
|
||||
/>
|
||||
<h1 class="create-pass__title">Objects</h1>
|
||||
<div class="create-pass__container">
|
||||
<GeneratePassphrase
|
||||
:is-loading="isLoading"
|
||||
:on-button-click="onNextClick"
|
||||
:set-parent-passphrase="setPassphrase"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -54,13 +57,36 @@ export default class CreatePassphrase extends Vue {
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
this.$router.push(RouteConfig.UploadFile.path);
|
||||
this.$router.push({
|
||||
name: RouteConfig.BucketsManagement.name,
|
||||
params: {
|
||||
passphrase: this.passphrase,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.create-pass {
|
||||
margin-top: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
color: #232b34;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&__container {
|
||||
margin-top: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -3,61 +3,64 @@
|
||||
|
||||
<template>
|
||||
<div class="enter-pass">
|
||||
<h1 class="enter-pass__title">Access Data in Browser</h1>
|
||||
<div class="enter-pass__warning">
|
||||
<div class="enter-pass__warning__header">
|
||||
<WarningIcon/>
|
||||
<p class="enter-pass__warning__header__label">Would you like to access files in your browser?</p>
|
||||
<h1 class="enter-pass__title">Objects</h1>
|
||||
<div class="enter-pass__container">
|
||||
<h1 class="enter-pass__container__title">Access Data in Browser</h1>
|
||||
<div class="enter-pass__container__warning">
|
||||
<div class="enter-pass__container__warning__header">
|
||||
<WarningIcon/>
|
||||
<p class="enter-pass__container__warning__header__label">Would you like to access files in your browser?</p>
|
||||
</div>
|
||||
<p class="enter-pass__container__warning__message">
|
||||
Entering your encryption passphrase here will share encryption data with your browser.
|
||||
<a
|
||||
class="enter-pass__container__warning__message__link"
|
||||
:href="docsLink"
|
||||
target="_blank"
|
||||
rel="noopener norefferer"
|
||||
>
|
||||
Learn More
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<p class="enter-pass__warning__message">
|
||||
Entering your encryption passphrase here will share encryption data with your browser.
|
||||
<a
|
||||
class="enter-pass__warning__message__link"
|
||||
:href="docsLink"
|
||||
target="_blank"
|
||||
rel="noopener norefferer"
|
||||
>
|
||||
Learn More
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<label class="enter-pass__textarea" for="enter-pass-textarea">
|
||||
<p class="enter-pass__textarea__label">Encryption Passphrase</p>
|
||||
<textarea
|
||||
class="enter-pass__textarea__input"
|
||||
:class="{ error: isError }"
|
||||
id="enter-pass-textarea"
|
||||
placeholder="Enter encryption passphrase here"
|
||||
rows="2"
|
||||
v-model="passphrase"
|
||||
@input="resetErrors"
|
||||
/>
|
||||
</label>
|
||||
<div class="enter-pass__error" v-if="isError">
|
||||
<h2 class="enter-pass__error__title">Encryption Passphrase Does not Match</h2>
|
||||
<p class="enter-pass__error__message">
|
||||
This passphrase hasn’t yet been used in the browser. Please ensure this is the encryption passphrase
|
||||
used in libulink or the Uplink CLI.
|
||||
</p>
|
||||
<label class="enter-pass__error__check-area" :class="{ error: isCheckboxError }" for="error-checkbox">
|
||||
<input
|
||||
class="enter-pass__error__check-area__checkbox"
|
||||
id="error-checkbox"
|
||||
type="checkbox"
|
||||
v-model="isCheckboxChecked"
|
||||
@change="isCheckboxError = false"
|
||||
>
|
||||
I acknowledge this passphrase has not been used in this browser before.
|
||||
<label class="enter-pass__container__textarea" for="enter-pass-textarea">
|
||||
<p class="enter-pass__container__textarea__label">Encryption Passphrase</p>
|
||||
<textarea
|
||||
class="enter-pass__container__textarea__input"
|
||||
:class="{ error: isError }"
|
||||
id="enter-pass-textarea"
|
||||
placeholder="Enter encryption passphrase here"
|
||||
rows="2"
|
||||
v-model="passphrase"
|
||||
@input="resetErrors"
|
||||
/>
|
||||
</label>
|
||||
<div class="enter-pass__container__error" v-if="isError">
|
||||
<h2 class="enter-pass__container__error__title">Encryption Passphrase Does not Match</h2>
|
||||
<p class="enter-pass__container__error__message">
|
||||
This passphrase hasn’t yet been used in the browser. Please ensure this is the encryption passphrase
|
||||
used in libulink or the Uplink CLI.
|
||||
</p>
|
||||
<label class="enter-pass__container__error__check-area" :class="{ error: isCheckboxError }" for="error-checkbox">
|
||||
<input
|
||||
class="enter-pass__container__error__check-area__checkbox"
|
||||
id="error-checkbox"
|
||||
type="checkbox"
|
||||
v-model="isCheckboxChecked"
|
||||
@change="isCheckboxError = false"
|
||||
>
|
||||
I acknowledge this passphrase has not been used in this browser before.
|
||||
</label>
|
||||
</div>
|
||||
<VButton
|
||||
class="enter-pass__container__next-button"
|
||||
label="Access Data"
|
||||
width="100%"
|
||||
height="48px"
|
||||
:on-press="onAccessDataClick"
|
||||
:is-disabled="!passphrase"
|
||||
/>
|
||||
</div>
|
||||
<VButton
|
||||
class="enter-pass__next-button"
|
||||
label="Access Data"
|
||||
width="100%"
|
||||
height="48px"
|
||||
:on-press="onAccessDataClick"
|
||||
:is-disabled="!passphrase"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -112,7 +115,12 @@ export default class EnterPassphrase extends Vue {
|
||||
switch (true) {
|
||||
case areHashesEqual() ||
|
||||
!areHashesEqual() && this.isError && this.isCheckboxChecked:
|
||||
this.$router.push(RouteConfig.UploadFile.path);
|
||||
this.$router.push({
|
||||
name: RouteConfig.BucketsManagement.name,
|
||||
params: {
|
||||
passphrase: this.passphrase,
|
||||
},
|
||||
});
|
||||
|
||||
return;
|
||||
case !areHashesEqual() && this.isError && !this.isCheckboxChecked:
|
||||
@ -141,114 +149,132 @@ export default class EnterPassphrase extends Vue {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.enter-pass {
|
||||
padding: 45px 50px 60px 50px;
|
||||
max-width: 515px;
|
||||
min-width: 515px;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-style: normal;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
margin: 100px 0 30px 0;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
line-height: 27px;
|
||||
color: #000;
|
||||
margin: 0 0 30px 0;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
color: #232b34;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&__warning {
|
||||
&__container {
|
||||
padding: 45px 50px 60px 50px;
|
||||
max-width: 515px;
|
||||
min-width: 515px;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-style: normal;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
width: calc(100% - 40px);
|
||||
background: #f5f6fa;
|
||||
border: 1px solid #a9b5c1;
|
||||
border-radius: 8px;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
margin: 100px 0 30px 0;
|
||||
|
||||
&__header {
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
line-height: 27px;
|
||||
color: #000;
|
||||
margin: 0 0 30px 0;
|
||||
}
|
||||
|
||||
&__warning {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
width: calc(100% - 40px);
|
||||
background: #f5f6fa;
|
||||
border: 1px solid #a9b5c1;
|
||||
border-radius: 8px;
|
||||
|
||||
&__label {
|
||||
font-style: normal;
|
||||
font-family: 'font_bold', sans-serif;
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&__label {
|
||||
font-style: normal;
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 19px;
|
||||
color: #1b2533;
|
||||
margin: 0 0 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-size: 16px;
|
||||
line-height: 19px;
|
||||
color: #1b2533;
|
||||
margin: 0 0 0 15px;
|
||||
margin: 10px 0 0 0;
|
||||
|
||||
&__link {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
color: #0068dc;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-size: 16px;
|
||||
line-height: 19px;
|
||||
color: #1b2533;
|
||||
margin: 10px 0 0 0;
|
||||
|
||||
&__link {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
color: #0068dc;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__textarea {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: #354049;
|
||||
margin: 26px 0 10px 0;
|
||||
|
||||
&__label {
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
&__input {
|
||||
padding: 15px 20px;
|
||||
resize: none;
|
||||
width: calc(100% - 42px);
|
||||
font-size: 14px;
|
||||
line-height: 25px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
color: #ce3030;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
&__textarea {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
margin: 0 0 5px 0;
|
||||
color: #354049;
|
||||
margin: 26px 0 10px 0;
|
||||
|
||||
&__label {
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
&__input {
|
||||
padding: 15px 20px;
|
||||
resize: none;
|
||||
width: calc(100% - 42px);
|
||||
font-size: 14px;
|
||||
line-height: 25px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-weight: normal;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
&__check-area {
|
||||
margin-bottom: 32px;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
color: #1b2533;
|
||||
&__error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
color: #ce3030;
|
||||
|
||||
&__checkbox {
|
||||
margin: 0 10px 0 0;
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-weight: normal;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
&__check-area {
|
||||
margin-bottom: 32px;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
color: #1b2533;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&__checkbox {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,6 @@
|
||||
|
||||
<template>
|
||||
<div class="objects-area">
|
||||
<div class="objects-area__header">
|
||||
<h1 class="objects-area__header__title">Objects</h1>
|
||||
</div>
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
@ -55,25 +52,5 @@ export default class ObjectsArea extends Vue {
|
||||
<style scoped lang="scss">
|
||||
.objects-area {
|
||||
padding: 20px 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
color: #232b34;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -18,6 +18,7 @@ import DetailedHistory from '@/components/account/billing/depositAndBillingHisto
|
||||
import CreditsHistory from '@/components/account/billing/freeCredits/CreditsHistory.vue';
|
||||
import SettingsArea from '@/components/account/SettingsArea.vue';
|
||||
import Page404 from '@/components/errors/Page404.vue';
|
||||
import BucketsView from '@/components/objects/BucketsView.vue';
|
||||
import CreatePassphrase from '@/components/objects/CreatePassphrase.vue';
|
||||
import EnterPassphrase from '@/components/objects/EnterPassphrase.vue';
|
||||
import ObjectsArea from '@/components/objects/ObjectsArea.vue';
|
||||
@ -90,6 +91,7 @@ export abstract class RouteConfig {
|
||||
// objects child paths.
|
||||
public static CreatePassphrase = new NavigationLink('create-passphrase', 'Objects Create Passphrase');
|
||||
public static EnterPassphrase = new NavigationLink('enter-passphrase', 'Objects Enter Passphrase');
|
||||
public static BucketsManagement = new NavigationLink('buckets', 'Buckets Management');
|
||||
public static UploadFile = new NavigationLink('upload', 'Objects Upload');
|
||||
}
|
||||
|
||||
@ -308,6 +310,12 @@ export const router = new Router({
|
||||
name: RouteConfig.EnterPassphrase.name,
|
||||
component: EnterPassphrase,
|
||||
},
|
||||
{
|
||||
path: RouteConfig.BucketsManagement.path,
|
||||
name: RouteConfig.BucketsManagement.name,
|
||||
component: BucketsView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: RouteConfig.UploadFile.path,
|
||||
name: RouteConfig.UploadFile.name,
|
||||
|
@ -15,6 +15,7 @@ import { AccessGrantsState, makeAccessGrantsModule } from '@/store/modules/acces
|
||||
import { appStateModule } from '@/store/modules/appState';
|
||||
import { makeBucketsModule } from '@/store/modules/buckets';
|
||||
import { makeNotificationsModule, NotificationsState } from '@/store/modules/notifications';
|
||||
import { makeObjectsModule, ObjectsState } from '@/store/modules/objects';
|
||||
import { makePaymentsModule, PaymentsState } from '@/store/modules/payments';
|
||||
import { makeProjectMembersModule, ProjectMembersState } from '@/store/modules/projectMembers';
|
||||
import { makeProjectsModule, ProjectsState, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
@ -46,6 +47,7 @@ class ModulesState {
|
||||
public paymentsModule: PaymentsState;
|
||||
public usersModule: User;
|
||||
public projectsModule: ProjectsState;
|
||||
public objectsModule: ObjectsState;
|
||||
}
|
||||
|
||||
// Satellite store (vuex)
|
||||
@ -59,6 +61,7 @@ export const store = new Vuex.Store<ModulesState>({
|
||||
usersModule: makeUsersModule(authApi),
|
||||
projectsModule: makeProjectsModule(projectsApi),
|
||||
bucketUsageModule: makeBucketsModule(bucketsApi),
|
||||
objectsModule: makeObjectsModule(),
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -17,6 +17,7 @@ export const ACCESS_GRANTS_ACTIONS = {
|
||||
FETCH: 'fetchAccessGrants',
|
||||
CREATE: 'createAccessGrant',
|
||||
DELETE: 'deleteAccessGrants',
|
||||
DELETE_BY_NAME_AND_PROJECT_ID: 'deleteAccessGrantsByNameAndProjectID',
|
||||
CLEAR: 'clearAccessGrants',
|
||||
GET_GATEWAY_CREDENTIALS: 'getGatewayCredentials',
|
||||
SET_ACCESS_GRANTS_WEB_WORKER: 'setAccessGrantsWebWorker',
|
||||
@ -210,10 +211,15 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
|
||||
deleteAccessGrants: async function({state}: any): Promise<void> {
|
||||
await api.delete(state.selectedAccessGrantsIds);
|
||||
},
|
||||
getGatewayCredentials: async function({state, commit}: any, accessGrant: string): Promise<void> {
|
||||
deleteAccessGrantsByNameAndProjectID: async function({state, rootGetters}: any, name: string): Promise<void> {
|
||||
await api.deleteByNameAndProjectID(name, rootGetters.selectedProject.id);
|
||||
},
|
||||
getGatewayCredentials: async function({state, commit}: any, accessGrant: string): Promise<GatewayCredentials> {
|
||||
const credentials: GatewayCredentials = await api.getGatewayCredentials(accessGrant);
|
||||
|
||||
commit(SET_GATEWAY_CREDENTIALS, credentials);
|
||||
|
||||
return credentials;
|
||||
},
|
||||
setAccessGrantsSearchQuery: function ({commit}, search: string) {
|
||||
commit(SET_SEARCH_QUERY, search);
|
||||
|
60
web/satellite/src/store/modules/objects.ts
Normal file
60
web/satellite/src/store/modules/objects.ts
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { StoreModule } from '@/store';
|
||||
import { GatewayCredentials } from '@/types/accessGrants';
|
||||
|
||||
export const OBJECTS_ACTIONS = {
|
||||
CLEAR: 'clearObjects',
|
||||
GET_GATEWAY_CREDENTIALS: 'getGatewayCredentials',
|
||||
SET_ACCESS_GRANT: 'setAccessGrant',
|
||||
};
|
||||
|
||||
export const OBJECTS_MUTATIONS = {
|
||||
SET_GATEWAY_CREDENTIALS: 'setGatewayCredentials',
|
||||
SET_ACCESS_GRANT: 'setAccessGrant',
|
||||
CLEAR: 'clearObjects',
|
||||
};
|
||||
|
||||
const {
|
||||
CLEAR,
|
||||
SET_ACCESS_GRANT,
|
||||
SET_GATEWAY_CREDENTIALS,
|
||||
} = OBJECTS_MUTATIONS;
|
||||
|
||||
export class ObjectsState {
|
||||
public accessGrant: string = '';
|
||||
public gatewayCredentials: GatewayCredentials = new GatewayCredentials();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates objects module with all dependencies.
|
||||
*/
|
||||
export function makeObjectsModule(): StoreModule<ObjectsState> {
|
||||
return {
|
||||
state: new ObjectsState(),
|
||||
mutations: {
|
||||
[SET_ACCESS_GRANT](state: ObjectsState, accessGrant: string) {
|
||||
state.accessGrant = accessGrant;
|
||||
},
|
||||
[SET_GATEWAY_CREDENTIALS](state: ObjectsState, credentials: GatewayCredentials) {
|
||||
state.gatewayCredentials = credentials;
|
||||
},
|
||||
[CLEAR](state: ObjectsState) {
|
||||
state.accessGrant = '';
|
||||
state.gatewayCredentials = new GatewayCredentials();
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setAccessGrant: function({commit}: any, accessGrant: string): void {
|
||||
commit(SET_ACCESS_GRANT, accessGrant);
|
||||
},
|
||||
setGatewayCredentials: function({commit}: any, credentials: GatewayCredentials): void {
|
||||
commit(SET_GATEWAY_CREDENTIALS, credentials);
|
||||
},
|
||||
clearObjects: function ({commit}: any): void {
|
||||
commit(CLEAR);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
@ -33,6 +33,14 @@ export interface AccessGrantsApi {
|
||||
*/
|
||||
delete(ids: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete existing access grant by name and project id
|
||||
*
|
||||
* @returns null
|
||||
* @throws Error
|
||||
*/
|
||||
deleteByNameAndProjectID(name: string, projectID: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get gateway credentials using access grant
|
||||
*
|
||||
|
@ -32,6 +32,10 @@ export class AccessGrantsMock implements AccessGrantsApi {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
deleteByNameAndProjectID(name: string, projectID: string): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getGatewayCredentials(accessGrant: string): Promise<GatewayCredentials> {
|
||||
return Promise.resolve(new GatewayCredentials('testCredId', new Date(), 'testAccessKeyId', 'testSecret', 'testEndpoint'));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user