297 lines
8.5 KiB
Svelte
297 lines
8.5 KiB
Svelte
<script lang="ts">
|
|
import { Database, Loader2 } from 'lucide-svelte'
|
|
import Toggle from './Toggle.svelte'
|
|
import { Button, Tab, Tabs } from './common'
|
|
import { SettingService } from '$lib/gen'
|
|
import { sendUserToast } from '$lib/toast'
|
|
import TestConnection from './TestConnection.svelte'
|
|
import { enterpriseLicense } from '$lib/stores'
|
|
import SimpleEditor from './SimpleEditor.svelte'
|
|
|
|
type S3Config = {
|
|
type: 'S3'
|
|
bucket: string
|
|
region: string
|
|
access_key: string
|
|
secret_key: string
|
|
endpoint: string
|
|
allow_http?: boolean
|
|
}
|
|
|
|
type AzureConfig = {
|
|
type: 'Azure'
|
|
accountName: string
|
|
containerName: string
|
|
useSSL?: boolean
|
|
tenantId: string
|
|
clientId: string
|
|
accessKey: string
|
|
endpoint?: string
|
|
}
|
|
|
|
type AwsOidcConfig = {
|
|
type: 'AwsOidc'
|
|
bucket: string
|
|
region: string
|
|
roleArn: string
|
|
}
|
|
|
|
type GcsConfig = {
|
|
type: 'Gcs'
|
|
bucket: string
|
|
serviceAccountKey: Record<string, string>
|
|
}
|
|
|
|
export let bucket_config: S3Config | AzureConfig | AwsOidcConfig | GcsConfig | undefined =
|
|
undefined
|
|
|
|
$: bucket_config?.type == 'S3' &&
|
|
bucket_config.allow_http == undefined &&
|
|
(bucket_config.allow_http = true)
|
|
let loading = false
|
|
|
|
async function testConnection() {
|
|
loading = true
|
|
try {
|
|
if (bucket_config) {
|
|
await SettingService.testObjectStorageConfig({
|
|
requestBody: bucket_config
|
|
})
|
|
sendUserToast('Connection successful', false)
|
|
}
|
|
} catch (e) {
|
|
sendUserToast(e.body, true)
|
|
} finally {
|
|
loading = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="my-0.5">
|
|
<Toggle
|
|
disabled={!$enterpriseLicense}
|
|
options={{ right: bucket_config ? '' : 'set object store' }}
|
|
checked={Boolean(bucket_config)}
|
|
on:change={(e) => {
|
|
if (e.detail) {
|
|
bucket_config = {
|
|
type: 'S3',
|
|
bucket: '',
|
|
region: '',
|
|
access_key: '',
|
|
secret_key: '',
|
|
endpoint: ''
|
|
}
|
|
} else {
|
|
bucket_config = undefined
|
|
}
|
|
}}
|
|
/>
|
|
</div>
|
|
{#if bucket_config}
|
|
<div class="p-2">
|
|
<div class="flex gap-2 py-1">
|
|
<Button
|
|
spacingSize="sm"
|
|
size="xs"
|
|
btnClasses="h-8"
|
|
variant="default"
|
|
on:click={testConnection}
|
|
>
|
|
{#if loading}
|
|
<Loader2 class="animate-spin mr-2 !h-4 !w-4" />
|
|
{:else}
|
|
<Database class="mr-2 !h-4 !w-4" />
|
|
{/if}
|
|
Test from a server
|
|
</Button>
|
|
<TestConnection
|
|
args={bucket_config}
|
|
resourceType="s3_bucket"
|
|
workspaceOverride="admins"
|
|
buttonTextOverride="Test from a worker"
|
|
/>
|
|
</div>
|
|
|
|
<Tabs
|
|
selected={bucket_config?.type ?? 'S3'}
|
|
on:selected={(e) => {
|
|
if (e.detail === 'S3' && bucket_config?.type !== 'S3') {
|
|
bucket_config = {
|
|
type: 'S3',
|
|
bucket: '',
|
|
region: '',
|
|
access_key: '',
|
|
secret_key: '',
|
|
endpoint: ''
|
|
}
|
|
} else if (e.detail === 'Azure' && bucket_config?.type !== 'Azure') {
|
|
bucket_config = {
|
|
type: 'Azure',
|
|
accountName: '',
|
|
containerName: '',
|
|
useSSL: false,
|
|
tenantId: '',
|
|
clientId: '',
|
|
accessKey: ''
|
|
}
|
|
} else if (e.detail === 'Gcs' && bucket_config?.type !== 'Gcs') {
|
|
bucket_config = {
|
|
type: 'Gcs',
|
|
bucket: '',
|
|
serviceAccountKey: {}
|
|
}
|
|
} else if (e.detail === 'AwsOidc' && bucket_config?.type !== 'AwsOidc') {
|
|
bucket_config = {
|
|
type: 'AwsOidc',
|
|
bucket: '',
|
|
region: '',
|
|
roleArn: ''
|
|
}
|
|
}
|
|
}}
|
|
>
|
|
<Tab value="S3" label="S3" />
|
|
<Tab value="Azure" label="Azure Blob" />
|
|
<Tab value="AwsOidc" label="AWS OIDC" />
|
|
<Tab value="Gcs" label="Google Cloud Storage" />
|
|
</Tabs>
|
|
<div class="flex flex-col gap-2 mt-2 p-2 border rounded-md">
|
|
{#if bucket_config.type === 'S3'}
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Bucket</span>
|
|
<input type="text" placeholder="bucket-name" bind:value={bucket_config.bucket} />
|
|
</label>
|
|
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Region</span>
|
|
<span class="text-primary text-2xs"
|
|
>If left empty, will be derived automatically from $AWS_REGION</span
|
|
>
|
|
<input type="text" bind:value={bucket_config.region} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Access key ID</span>
|
|
<span class="text-primary text-2xs"
|
|
>If left empty, will be derived automatically from $AWS_ACCESS_KEY_ID, pod or ec2
|
|
profile</span
|
|
>
|
|
<input type="text" bind:value={bucket_config.access_key} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Secret key</span>
|
|
<span class="text-primary text-2xs"
|
|
>If left empty, will be derived automatically from $AWS_SECRET_KEY, pod or ec2 profile</span
|
|
>
|
|
<input
|
|
type="password"
|
|
autocomplete="new-password"
|
|
bind:value={bucket_config.secret_key}
|
|
/>
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Endpoint</span>
|
|
<span class="text-primary text-2xs"
|
|
>Only needed for non AWS S3 providers like R2 or MinIo</span
|
|
>
|
|
<input type="text" bind:value={bucket_config.endpoint} />
|
|
</label>
|
|
<div class="block pb-2">
|
|
<span class="text-primary text-2xs">Disable if using https only policy</span>
|
|
<div>
|
|
<Toggle bind:checked={bucket_config.allow_http} options={{ right: 'Allow http' }} />
|
|
</div>
|
|
</div>
|
|
{:else if bucket_config.type === 'Azure'}
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Account name</span>
|
|
<input type="text" placeholder="account-name" bind:value={bucket_config.accountName} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Container name</span>
|
|
<input
|
|
type="text"
|
|
placeholder="container-name"
|
|
bind:value={bucket_config.containerName}
|
|
/>
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Access key</span>
|
|
<input type="password" autocomplete="new-password" bind:value={bucket_config.accessKey} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis"
|
|
>Tenant ID <span class="text-2xs text-primary">(optional)</span></span
|
|
>
|
|
<input type="text" bind:value={bucket_config.tenantId} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis"
|
|
>Client ID <span class="text-2xs text-primary">(optional)</span></span
|
|
>
|
|
<input type="text" bind:value={bucket_config.clientId} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis"
|
|
>Endpoint <span class="text-2xs text-primary">(optional)</span></span
|
|
>
|
|
<span class="text-primary text-2xs"
|
|
>Only needed for non Azure Blob providers like Azurite</span
|
|
>
|
|
<input type="text" bind:value={bucket_config.endpoint} />
|
|
</label>
|
|
{:else if bucket_config.type === 'AwsOidc'}
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Bucket</span>
|
|
<input type="text" placeholder="bucket-name" bind:value={bucket_config.bucket} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Region</span>
|
|
<input type="text" placeholder="region" bind:value={bucket_config.region} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Role ARN</span>
|
|
<input
|
|
type="text"
|
|
placeholder="arn:aws:iam::123456789012:role/test"
|
|
bind:value={bucket_config.roleArn}
|
|
/>
|
|
</label>
|
|
{:else if bucket_config.type === 'Gcs'}
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Bucket</span>
|
|
<input type="text" placeholder="bucket-name" bind:value={bucket_config.bucket} />
|
|
</label>
|
|
<label class="block pb-2">
|
|
<span class="text-xs font-semibold text-emphasis">Service Account Key</span>
|
|
<span class="text-primary text-2xs">JSON content of the service account key file</span>
|
|
<SimpleEditor
|
|
lang="json"
|
|
bind:code={
|
|
() => {
|
|
if (bucket_config?.type === 'Gcs') {
|
|
return JSON.stringify(bucket_config.serviceAccountKey)
|
|
} else {
|
|
return '{}'
|
|
}
|
|
},
|
|
(v) => {
|
|
if (bucket_config?.type === 'Gcs') {
|
|
try {
|
|
bucket_config.serviceAccountKey = JSON.parse(v ?? '{}')
|
|
} catch (_) {
|
|
bucket_config.serviceAccountKey = {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
class="h-80"
|
|
/>
|
|
</label>
|
|
{:else}
|
|
<div>Unknown bucket type {bucket_config['type']}</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
{/if}
|