123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- import * as Sentry from '@sentry/react';
- import {Field} from 'sentry/components/forms/type';
- 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, t(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: 'user@project.iam.gserviceaccount.com',
- 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
- }
- }
- }
|