Skip to content

Commit

Permalink
web/satellite: extend setup application flow to support API keys and …
Browse files Browse the repository at this point in the history
…Access grants

Extended setup application flow to be universal Create Access flow (added API keys and Access grants support).
Replaced old create access flow with the new one (behind new setup app flow feature flag).

Issue:
#6882

Change-Id: Ia83159834f3d6c034605b43dbd955fdf57087f3a
  • Loading branch information
VitaliiShpital authored and Storj Robot committed Apr 10, 2024
1 parent 200d08d commit 175840e
Show file tree
Hide file tree
Showing 14 changed files with 774 additions and 221 deletions.
11 changes: 9 additions & 2 deletions web/satellite/src/components/ApplicationItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@
</v-card-item>
</v-card>
</v-col>
<AppSetupDialog v-if="newAppSetupFlowEnabled" v-model="dialog" :access-name="app.name" :docs-link="app.docs" />
<AccessSetupDialog
v-if="newAppSetupFlowEnabled"
v-model="dialog"
:access-name="app.name"
:docs-link="app.docs"
:default-access-type="AccessType.S3"
is-app-setup
/>
<CreateAccessDialog v-else ref="accessDialog" v-model="dialog" :default-name="app.name" />
</template>

Expand All @@ -51,7 +58,7 @@ import { useTrialCheck } from '@/composables/useTrialCheck';
import { useConfigStore } from '@/store/modules/configStore';
import CreateAccessDialog from '@/components/dialogs/CreateAccessDialog.vue';
import AppSetupDialog from '@/components/dialogs/AppSetupDialog.vue';
import AccessSetupDialog from '@/components/dialogs/AccessSetupDialog.vue';
defineProps<{
app: Application
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

<template>
<v-form class="pa-7">
<v-row>
<v-col>
<p class="font-weight-bold mb-2">Access Created</p>
<p>
Copy and save the access credentials {{ isAppSetup ? 'for this application' : '' }} as they will only appear once.
</p>
<v-row class="mt-2">
<save-buttons :items="saveItems" :name="name" :type="accessType" />
</v-row>
</v-col>

<template v-if="accessType === AccessType.APIKey">
<v-col cols="12">
<v-text-field
flat
density="comfortable"
label="Satellite Address"
:model-value="satelliteAddress"
readonly
hide-details
>
<template #append-inner>
<input-copy-button :value="satelliteAddress" />
</template>
</v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
flat
density="comfortable"
label="API Key"
:model-value="cliAccess"
readonly
hide-details
>
<template #append-inner>
<input-copy-button :value="cliAccess" />
</template>
</v-text-field>
</v-col>
</template>

<v-col v-else-if="accessType === AccessType.AccessGrant" cols="12">
<v-text-field
flat
density="comfortable"
label="Access Grant"
:model-value="accessGrant"
readonly
hide-details
>
<template #append-inner>
<input-copy-button :value="accessGrant" />
</template>
</v-text-field>
</v-col>

<template v-else>
<v-col cols="12">
<v-text-field
flat
density="comfortable"
label="Access Key"
:model-value="credentials.accessKeyId"
readonly
hide-details
>
<template #append-inner>
<input-copy-button :value="credentials.accessKeyId" />
</template>
</v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
flat
density="comfortable"
label="Secret Key"
:model-value="credentials.secretKey"
readonly
hide-details
>
<template #append-inner>
<input-copy-button :value="credentials.secretKey" />
</template>
</v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
flat
density="comfortable"
label="Endpoint"
:model-value="credentials.endpoint"
readonly
hide-details
>
<template #append-inner>
<input-copy-button :value="credentials.endpoint" />
</template>
</v-text-field>
</v-col>
</template>

<v-col>
<v-alert variant="tonal" color="info">
<p class="text-subtitle-2 font-weight-bold">Next steps</p>
<p class="text-subtitle-2">Please read the documentation to find where to enter the access you created.</p>
</v-alert>
</v-col>
</v-row>
</v-form>
</template>

<script setup lang="ts">
import { VAlert, VCol, VForm, VRow, VTextField } from 'vuetify/components';
import { computed } from 'vue';
import { EdgeCredentials } from '@/types/accessGrants';
import { AccessType } from '@/types/createAccessGrant';
import { useConfigStore } from '@/store/modules/configStore';
import { SaveButtonsItem } from '@/types/common';
import InputCopyButton from '@/components/InputCopyButton.vue';
import SaveButtons from '@/components/dialogs/commonPassphraseSteps/SaveButtons.vue';
const props = defineProps<{
name: string
isAppSetup: boolean
accessType: AccessType
cliAccess: string
accessGrant: string
credentials: EdgeCredentials
}>();
const configStore = useConfigStore();
const satelliteAddress = computed<string>(() => configStore.state.config.satelliteNodeURL);
/**
* Returns items for save/download buttons based on access type.
*/
const saveItems = computed<SaveButtonsItem[]>(() => {
if (props.accessType === AccessType.APIKey) {
return [
{ name: 'Satellite Address', value: satelliteAddress.value },
{ name: 'API Key', value: props.cliAccess },
];
}
if (props.accessType === AccessType.AccessGrant) {
return [props.accessGrant];
}
return [
{ name: 'Access Key', value: props.credentials.accessKeyId },
{ name: 'Secret Key', value: props.credentials.secretKey },
{ name: 'Endpoint', value: props.credentials.endpoint },
];
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

<template>
<v-form ref="form" class="pa-7" @submit.prevent>
<v-row>
<v-col cols="12">
<p class="text-subtitle-2 font-weight-bold mb-5">Enter Access Name</p>
<v-text-field
v-model="name"
label="Access Name"
variant="outlined"
autofocus
:hide-details="false"
:rules="nameRules"
maxlength="100"
class="mb-n2"
required
/>
</v-col>
<v-col>
<p class="text-subtitle-2 font-weight-bold mb-4">Choose Access Type</p>
<v-chip-group
v-model="accessType"
class="mb-3"
selected-class="font-weight-bold"
color="info"
mandatory
column
>
<v-chip
:key="AccessType.S3"
:value="AccessType.S3"
color="info"
variant="outlined"
rounded
filter
>
S3 Credentials
</v-chip>

<v-chip
:key="AccessType.AccessGrant"
:value="AccessType.AccessGrant"
color="info"
variant="outlined"
rounded
filter
>
Access Grant
</v-chip>

<v-chip
:key="AccessType.APIKey"
:value="AccessType.APIKey"
color="info"
variant="outlined"
rounded
filter
>
API Key
</v-chip>
</v-chip-group>

<v-alert v-if="accessType === AccessType.S3" variant="tonal" color="info" width="auto">
<p class="text-subtitle-2">Gives access through S3 compatible applications. <a href="https://docs.storj.io/dcs/access#create-s3-credentials" target="_blank" rel="noopener noreferrer" class="link">Learn more in the documentation.</a></p>
</v-alert>

<v-alert v-else-if="accessType === AccessType.AccessGrant" variant="tonal" color="info" width="auto">
<p class="text-subtitle-2">Gives access through native clients such as uplink. <a href="https://docs.storj.io/learn/concepts/access/access-grants" target="_blank" rel="noopener noreferrer" class="link">Learn more in the documentation.</a></p>
</v-alert>

<v-alert v-else-if="accessType === AccessType.APIKey" variant="tonal" color="info" width="auto">
<p class="text-subtitle-2">Use it for generating access keys programatically. <a href="https://docs.storj.io/learn/concepts/access/access-grants/api-key" target="_blank" rel="noopener noreferrer" class="link">Learn more in the documentation.</a></p>
</v-alert>
</v-col>
</v-row>
</v-form>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import { VAlert, VChip, VChipGroup, VCol, VForm, VRow, VTextField } from 'vuetify/components';
import { AccessType } from '@/types/createAccessGrant';
import { IDialogFlowStep, RequiredRule, ValidationRule } from '@/types/common';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
const agStore = useAccessGrantsStore();
const emit = defineEmits<{
'nameChanged': [name: string];
'typeChanged': [type: AccessType];
}>();
const form = ref<VForm | null>(null);
const name = ref<string>('');
const accessType = ref<AccessType>(AccessType.S3);
const nameRules: ValidationRule<string>[] = [
RequiredRule,
v => !agStore.state.allAGNames.includes(v) || 'This name is already in use',
];
watch(name, value => emit('nameChanged', value));
watch(accessType, value => emit('typeChanged', value));
defineExpose<IDialogFlowStep>({
validate: () => {
form.value?.validate();
return !!form.value?.isValid;
},
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

<template>
<v-form class="pa-7" @submit.prevent>
<v-row>
<v-col>
<p v-if="isAppSetup">Setup access to third-party applications.</p>
<p v-else class="text-subtitle-2 font-weight-bold mb-4">Choose Setup Flow</p>
<v-chip-group
v-model="flowType"
class="my-3"
selected-class="font-weight-bold"
color="primary"
mandatory
column
@update:modelValue="val => emit('setFlowType', val)"
>
<v-chip
:key="FlowType.FullAccess"
:value="FlowType.FullAccess"
color="success"
variant="outlined"
rounded
filter
>
Full Access
</v-chip>
<v-chip
:key="FlowType.Advanced"
:value="FlowType.Advanced"
color="secondary"
variant="outlined"
rounded
filter
>
Advanced
</v-chip>
</v-chip-group>
<v-alert v-if="flowType === FlowType.FullAccess" variant="tonal" color="success" width="auto">
<template v-if="isAppSetup">
<p class="text-subtitle-2 font-weight-bold">Full Access</p>
<p class="text-subtitle-2">
The app will be provided full permissions access to all the buckets in this project. 1-click setup.
</p>
<p class="text-subtitle-2 font-weight-bold">Best for trying out an app.</p>
</template>
<p v-else class="text-subtitle-2">
The access key will have full permissions access to all the buckets and data in this project.
</p>
</v-alert>
<v-alert v-else variant="tonal" color="secondary" width="auto">
<template v-if="isAppSetup">
<p class="text-subtitle-2 font-weight-bold">Advanced Setup</p>
<p class="text-subtitle-2">
You can choose what permissions to give this app, and which buckets it can access in this project.
</p>
<p class="text-subtitle-2 font-weight-bold">Select if you want more control of the access.</p>
</template>
<p v-else class="text-subtitle-2">
You can choose the permissions, select buckets, and set an expiry date for this access key.
</p>
</v-alert>
</v-col>
</v-row>
</v-form>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { VAlert, VChip, VChipGroup, VCol, VForm, VRow } from 'vuetify/components';
import { FlowType } from '@/types/createAccessGrant';
import { IDialogFlowStep } from '@/types/common';
withDefaults(defineProps<{
isAppSetup?: boolean
}>(), {
isAppSetup: false,
});
const emit = defineEmits<{
'setFlowType': [flowType: FlowType]
}>();
const flowType = ref<FlowType>(FlowType.FullAccess);
defineExpose<IDialogFlowStep>({
onExit: () => {
emit('setFlowType', flowType.value);
},
});
</script>

0 comments on commit 175840e

Please sign in to comment.