mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
240 lines
6.6 KiB
TypeScript
240 lines
6.6 KiB
TypeScript
import * as Sentry from '@sentry/react';
|
|
|
|
import type {Field} from 'sentry/components/forms/types';
|
|
import ExternalLink from 'sentry/components/links/externalLink';
|
|
import {
|
|
AWS_REGIONS,
|
|
DEBUG_SOURCE_CASINGS,
|
|
DEBUG_SOURCE_LAYOUTS,
|
|
} from 'sentry/data/debugFileSources';
|
|
import {t, tct} from 'sentry/locale';
|
|
import {CustomRepoType} from 'sentry/types/debugFiles';
|
|
import {uniqueId} from 'sentry/utils/guid';
|
|
|
|
function objectToChoices(obj: Record<string, string>): [key: string, value: string][] {
|
|
return Object.entries(obj).map(([key, value]) => [key, value]);
|
|
}
|
|
|
|
type FieldMap = Record<string, Field>;
|
|
|
|
const commonFields: FieldMap = {
|
|
id: {
|
|
name: 'id',
|
|
type: 'hidden',
|
|
required: true,
|
|
defaultValue: uniqueId,
|
|
},
|
|
name: {
|
|
name: 'name',
|
|
type: 'string',
|
|
required: true,
|
|
label: t('Name'),
|
|
placeholder: t('New Repository'),
|
|
help: t('A display name for this repository'),
|
|
},
|
|
// filters are explicitly not exposed to the UI
|
|
layoutType: {
|
|
name: 'layout.type',
|
|
type: 'select',
|
|
label: t('Directory Layout'),
|
|
help: t('The layout of the folder structure.'),
|
|
defaultValue: 'native',
|
|
choices: objectToChoices(DEBUG_SOURCE_LAYOUTS),
|
|
},
|
|
layoutCasing: {
|
|
name: 'layout.casing',
|
|
type: 'select',
|
|
label: t('Path Casing'),
|
|
help: t('The case of files and folders.'),
|
|
defaultValue: 'default',
|
|
choices: objectToChoices(DEBUG_SOURCE_CASINGS),
|
|
},
|
|
prefix: {
|
|
name: 'prefix',
|
|
type: 'string',
|
|
label: 'Root Path',
|
|
placeholder: '/',
|
|
help: t('The path at which files are located within this repository.'),
|
|
},
|
|
separator: {
|
|
name: '',
|
|
type: 'separator',
|
|
},
|
|
};
|
|
|
|
export function getFormFieldsAndInitialData(
|
|
type: CustomRepoType,
|
|
sourceConfig?: Record<string, any>
|
|
) {
|
|
if (type === CustomRepoType.HTTP || type === CustomRepoType.APP_STORE_CONNECT) {
|
|
return {};
|
|
}
|
|
|
|
const {secret_key, layout, private_key, ...config} = sourceConfig ?? {};
|
|
const initialData = layout
|
|
? {...config, 'layout.casing': layout.casing, 'layout.type': layout.type}
|
|
: config;
|
|
|
|
switch (type) {
|
|
case 's3':
|
|
return {
|
|
fields: [
|
|
commonFields.id,
|
|
commonFields.name,
|
|
commonFields.separator,
|
|
{
|
|
name: 'bucket',
|
|
type: 'string',
|
|
required: true,
|
|
label: t('Bucket'),
|
|
placeholder: 's3-bucket-name',
|
|
help: t(
|
|
'Name of the S3 bucket. Read permissions are required to download symbols.'
|
|
),
|
|
},
|
|
{
|
|
name: 'region',
|
|
type: 'select',
|
|
required: true,
|
|
label: t('Region'),
|
|
help: t('The AWS region and availability zone of the bucket.'),
|
|
choices: AWS_REGIONS.map(([k, v]) => [
|
|
k,
|
|
<span key={k}>
|
|
<code>{k}</code> {v}
|
|
</span>,
|
|
]),
|
|
},
|
|
{
|
|
name: 'access_key',
|
|
type: 'string',
|
|
required: true,
|
|
label: t('Access Key ID'),
|
|
placeholder: 'AKIAIOSFODNN7EXAMPLE',
|
|
help: tct(
|
|
'Access key to the AWS account. Credentials can be managed in the [link].',
|
|
{
|
|
link: (
|
|
<ExternalLink href="https://console.aws.amazon.com/iam/">
|
|
IAM console
|
|
</ExternalLink>
|
|
),
|
|
}
|
|
),
|
|
},
|
|
{
|
|
name: 'secret_key',
|
|
type: 'string',
|
|
required: true,
|
|
label: t('Secret Access Key'),
|
|
placeholder:
|
|
typeof secret_key === 'object'
|
|
? t('(Secret Access Key unchanged)')
|
|
: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
|
|
},
|
|
commonFields.separator,
|
|
commonFields.prefix,
|
|
commonFields.layoutType,
|
|
commonFields.layoutCasing,
|
|
],
|
|
initialData: !initialData
|
|
? undefined
|
|
: {
|
|
...initialData,
|
|
secret_key: undefined,
|
|
},
|
|
};
|
|
case 'gcs':
|
|
return {
|
|
fields: [
|
|
commonFields.id,
|
|
commonFields.name,
|
|
commonFields.separator,
|
|
{
|
|
name: 'bucket',
|
|
type: 'string',
|
|
required: true,
|
|
label: t('Bucket'),
|
|
placeholder: 'gcs-bucket-name',
|
|
help: t(
|
|
'Name of the GCS bucket. Read permissions are required to download symbols.'
|
|
),
|
|
},
|
|
{
|
|
name: 'client_email',
|
|
type: 'email',
|
|
required: true,
|
|
label: t('Client Email'),
|
|
placeholder: '[email protected]',
|
|
help: t('Email address of the GCS service account.'),
|
|
},
|
|
{
|
|
name: 'private_key',
|
|
type: 'string',
|
|
required: true,
|
|
multiline: true,
|
|
autosize: true,
|
|
maxRows: 5,
|
|
rows: 3,
|
|
label: t('Private Key'),
|
|
placeholder:
|
|
typeof private_key === 'object'
|
|
? t('(Private Key unchanged)')
|
|
: '-----BEGIN PRIVATE KEY-----\n[PRIVATE-KEY]\n-----END PRIVATE KEY-----',
|
|
help: tct(
|
|
'The service account key. Credentials can be managed on the [link].',
|
|
{
|
|
link: (
|
|
<ExternalLink href="https://console.cloud.google.com/project/_/iam-admin">
|
|
IAM & Admin Page
|
|
</ExternalLink>
|
|
),
|
|
}
|
|
),
|
|
},
|
|
commonFields.separator,
|
|
commonFields.prefix,
|
|
commonFields.layoutType,
|
|
commonFields.layoutCasing,
|
|
],
|
|
initialData: !initialData
|
|
? undefined
|
|
: {
|
|
...initialData,
|
|
private_key: undefined,
|
|
},
|
|
};
|
|
default: {
|
|
Sentry.captureException(new Error('Unknown custom repository type'));
|
|
return {}; // this shall never happen
|
|
}
|
|
}
|
|
}
|
|
|
|
export function getFinalData(type: CustomRepoType, data: Record<string, any>) {
|
|
if (type === CustomRepoType.HTTP || type === CustomRepoType.APP_STORE_CONNECT) {
|
|
return data;
|
|
}
|
|
|
|
switch (type) {
|
|
case 's3':
|
|
return {
|
|
...data,
|
|
secret_key: data.secret_key ?? {
|
|
'hidden-secret': true,
|
|
},
|
|
};
|
|
case 'gcs':
|
|
return {
|
|
...data,
|
|
private_key: data.private_key ?? {
|
|
'hidden-secret': true,
|
|
},
|
|
};
|
|
default: {
|
|
Sentry.captureException(new Error('Unknown custom repository type'));
|
|
return {}; // this shall never happen
|
|
}
|
|
}
|
|
}
|