useFileUploadSettings.spec.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. import { describe, it, expect } from 'vitest';
  2. import type { FileUploadFormValues, FileUploadSettingsData } from './FileUploadSetting.types';
  3. /**
  4. * Helper function to build settings data (mimics useFileUploadSettings fetchData logic)
  5. */
  6. function buildSettingsData(appSettingsParams: Record<string, any>): FileUploadSettingsData {
  7. return {
  8. // File upload type
  9. fileUploadType: appSettingsParams.useOnlyEnvVarForFileUploadType
  10. ? appSettingsParams.envFileUploadType
  11. : appSettingsParams.fileUploadType,
  12. isFixedFileUploadByEnvVar: appSettingsParams.useOnlyEnvVarForFileUploadType || false,
  13. envFileUploadType: appSettingsParams.envFileUploadType,
  14. // AWS S3
  15. s3Region: appSettingsParams.s3Region || '',
  16. s3CustomEndpoint: appSettingsParams.s3CustomEndpoint || '',
  17. s3Bucket: appSettingsParams.s3Bucket || '',
  18. s3AccessKeyId: appSettingsParams.s3AccessKeyId || '',
  19. s3SecretAccessKey: appSettingsParams.s3SecretAccessKey || '',
  20. s3ReferenceFileWithRelayMode: appSettingsParams.s3ReferenceFileWithRelayMode || false,
  21. // GCS
  22. gcsApiKeyJsonPath: appSettingsParams.gcsApiKeyJsonPath || '',
  23. gcsBucket: appSettingsParams.gcsBucket || '',
  24. gcsUploadNamespace: appSettingsParams.gcsUploadNamespace || '',
  25. gcsReferenceFileWithRelayMode: appSettingsParams.gcsReferenceFileWithRelayMode || false,
  26. gcsUseOnlyEnvVars: appSettingsParams.gcsUseOnlyEnvVars || false,
  27. envGcsApiKeyJsonPath: appSettingsParams.envGcsApiKeyJsonPath,
  28. envGcsBucket: appSettingsParams.envGcsBucket,
  29. envGcsUploadNamespace: appSettingsParams.envGcsUploadNamespace,
  30. // Azure
  31. azureTenantId: appSettingsParams.azureTenantId || '',
  32. azureClientId: appSettingsParams.azureClientId || '',
  33. azureClientSecret: appSettingsParams.azureClientSecret || '',
  34. azureStorageAccountName: appSettingsParams.azureStorageAccountName || '',
  35. azureStorageContainerName: appSettingsParams.azureStorageContainerName || '',
  36. azureReferenceFileWithRelayMode: appSettingsParams.azureReferenceFileWithRelayMode || false,
  37. azureUseOnlyEnvVars: appSettingsParams.azureUseOnlyEnvVars || false,
  38. envAzureTenantId: appSettingsParams.envAzureTenantId,
  39. envAzureClientId: appSettingsParams.envAzureClientId,
  40. envAzureClientSecret: appSettingsParams.envAzureClientSecret,
  41. envAzureStorageAccountName: appSettingsParams.envAzureStorageAccountName,
  42. envAzureStorageContainerName: appSettingsParams.envAzureStorageContainerName,
  43. };
  44. }
  45. /**
  46. * Helper function to build request params (mimics useFileUploadSettings updateSettings logic)
  47. */
  48. function buildRequestParams(
  49. formData: FileUploadFormValues,
  50. dirtyFields: Partial<Record<keyof FileUploadFormValues, boolean>>,
  51. ): Record<string, any> {
  52. const { fileUploadType } = formData;
  53. const requestParams: Record<string, any> = {
  54. fileUploadType,
  55. };
  56. if (fileUploadType === 'aws') {
  57. requestParams.s3Region = formData.s3Region;
  58. requestParams.s3CustomEndpoint = formData.s3CustomEndpoint;
  59. requestParams.s3Bucket = formData.s3Bucket;
  60. requestParams.s3AccessKeyId = formData.s3AccessKeyId;
  61. // Only include secret access key if it was changed
  62. if (dirtyFields.s3SecretAccessKey) {
  63. requestParams.s3SecretAccessKey = formData.s3SecretAccessKey;
  64. }
  65. requestParams.s3ReferenceFileWithRelayMode = formData.s3ReferenceFileWithRelayMode;
  66. }
  67. if (fileUploadType === 'gcs') {
  68. requestParams.gcsApiKeyJsonPath = formData.gcsApiKeyJsonPath;
  69. requestParams.gcsBucket = formData.gcsBucket;
  70. requestParams.gcsUploadNamespace = formData.gcsUploadNamespace;
  71. requestParams.gcsReferenceFileWithRelayMode = formData.gcsReferenceFileWithRelayMode;
  72. }
  73. if (fileUploadType === 'azure') {
  74. // Only include secret fields if they were changed
  75. if (dirtyFields.azureTenantId) {
  76. requestParams.azureTenantId = formData.azureTenantId;
  77. }
  78. if (dirtyFields.azureClientId) {
  79. requestParams.azureClientId = formData.azureClientId;
  80. }
  81. if (dirtyFields.azureClientSecret) {
  82. requestParams.azureClientSecret = formData.azureClientSecret;
  83. }
  84. requestParams.azureStorageAccountName = formData.azureStorageAccountName;
  85. requestParams.azureStorageContainerName = formData.azureStorageContainerName;
  86. requestParams.azureReferenceFileWithRelayMode = formData.azureReferenceFileWithRelayMode;
  87. }
  88. return requestParams;
  89. }
  90. describe('useFileUploadSettings - fileUploadType selection with useOnlyEnvVarForFileUploadType', () => {
  91. it('should use envFileUploadType when useOnlyEnvVarForFileUploadType is true', () => {
  92. const appSettingsParams = {
  93. fileUploadType: 'local',
  94. envFileUploadType: 'aws',
  95. useOnlyEnvVarForFileUploadType: true,
  96. };
  97. const settingsData = buildSettingsData(appSettingsParams);
  98. expect(settingsData.fileUploadType).toBe('aws');
  99. expect(settingsData.isFixedFileUploadByEnvVar).toBe(true);
  100. expect(settingsData.envFileUploadType).toBe('aws');
  101. });
  102. it('should use fileUploadType when useOnlyEnvVarForFileUploadType is false', () => {
  103. const appSettingsParams = {
  104. fileUploadType: 'gcs',
  105. envFileUploadType: 'aws',
  106. useOnlyEnvVarForFileUploadType: false,
  107. };
  108. const settingsData = buildSettingsData(appSettingsParams);
  109. expect(settingsData.fileUploadType).toBe('gcs');
  110. expect(settingsData.isFixedFileUploadByEnvVar).toBe(false);
  111. expect(settingsData.envFileUploadType).toBe('aws');
  112. });
  113. it('should use fileUploadType when useOnlyEnvVarForFileUploadType is undefined', () => {
  114. const appSettingsParams = {
  115. fileUploadType: 'azure',
  116. envFileUploadType: 'aws',
  117. };
  118. const settingsData = buildSettingsData(appSettingsParams);
  119. expect(settingsData.fileUploadType).toBe('azure');
  120. expect(settingsData.isFixedFileUploadByEnvVar).toBe(false);
  121. });
  122. it('should prioritize envFileUploadType over fileUploadType when env var is enforced', () => {
  123. const appSettingsParams = {
  124. fileUploadType: 'local',
  125. envFileUploadType: 'gcs',
  126. useOnlyEnvVarForFileUploadType: true,
  127. };
  128. const settingsData = buildSettingsData(appSettingsParams);
  129. // Even though DB has 'local', env var 'gcs' should be used
  130. expect(settingsData.fileUploadType).toBe('gcs');
  131. expect(settingsData.isFixedFileUploadByEnvVar).toBe(true);
  132. });
  133. });
  134. describe('useFileUploadSettings - secret field dirty tracking', () => {
  135. it('should NOT include s3SecretAccessKey in request when it is not dirty (AWS)', () => {
  136. const formData: FileUploadFormValues = {
  137. fileUploadType: 'aws',
  138. s3Region: 'us-west-2',
  139. s3CustomEndpoint: '',
  140. s3Bucket: 'new-bucket',
  141. s3AccessKeyId: 'new-key-id',
  142. s3SecretAccessKey: '***existing-secret***', // Not changed
  143. s3ReferenceFileWithRelayMode: true,
  144. gcsApiKeyJsonPath: '',
  145. gcsBucket: '',
  146. gcsUploadNamespace: '',
  147. gcsReferenceFileWithRelayMode: false,
  148. azureTenantId: '',
  149. azureClientId: '',
  150. azureClientSecret: '',
  151. azureStorageAccountName: '',
  152. azureStorageContainerName: '',
  153. azureReferenceFileWithRelayMode: false,
  154. };
  155. const dirtyFields = {
  156. s3Region: true,
  157. s3Bucket: true,
  158. s3AccessKeyId: true,
  159. s3ReferenceFileWithRelayMode: true,
  160. // s3SecretAccessKey is NOT marked as dirty
  161. };
  162. const requestParams = buildRequestParams(formData, dirtyFields);
  163. expect(requestParams).toEqual({
  164. fileUploadType: 'aws',
  165. s3Region: 'us-west-2',
  166. s3CustomEndpoint: '',
  167. s3Bucket: 'new-bucket',
  168. s3AccessKeyId: 'new-key-id',
  169. s3ReferenceFileWithRelayMode: true,
  170. });
  171. // Verify s3SecretAccessKey is NOT in the request
  172. expect(requestParams).not.toHaveProperty('s3SecretAccessKey');
  173. });
  174. it('should include s3SecretAccessKey in request when it is dirty (AWS)', () => {
  175. const formData: FileUploadFormValues = {
  176. fileUploadType: 'aws',
  177. s3Region: 'us-west-2',
  178. s3CustomEndpoint: '',
  179. s3Bucket: 'new-bucket',
  180. s3AccessKeyId: 'new-key-id',
  181. s3SecretAccessKey: 'new-secret-key', // Changed
  182. s3ReferenceFileWithRelayMode: true,
  183. gcsApiKeyJsonPath: '',
  184. gcsBucket: '',
  185. gcsUploadNamespace: '',
  186. gcsReferenceFileWithRelayMode: false,
  187. azureTenantId: '',
  188. azureClientId: '',
  189. azureClientSecret: '',
  190. azureStorageAccountName: '',
  191. azureStorageContainerName: '',
  192. azureReferenceFileWithRelayMode: false,
  193. };
  194. const dirtyFields = {
  195. s3Region: true,
  196. s3Bucket: true,
  197. s3AccessKeyId: true,
  198. s3SecretAccessKey: true, // Marked as dirty
  199. s3ReferenceFileWithRelayMode: true,
  200. };
  201. const requestParams = buildRequestParams(formData, dirtyFields);
  202. expect(requestParams).toEqual({
  203. fileUploadType: 'aws',
  204. s3Region: 'us-west-2',
  205. s3CustomEndpoint: '',
  206. s3Bucket: 'new-bucket',
  207. s3AccessKeyId: 'new-key-id',
  208. s3SecretAccessKey: 'new-secret-key',
  209. s3ReferenceFileWithRelayMode: true,
  210. });
  211. });
  212. it('should include empty string for s3SecretAccessKey when explicitly set to empty (AWS)', () => {
  213. const formData: FileUploadFormValues = {
  214. fileUploadType: 'aws',
  215. s3Region: 'us-west-2',
  216. s3CustomEndpoint: '',
  217. s3Bucket: 'new-bucket',
  218. s3AccessKeyId: 'new-key-id',
  219. s3SecretAccessKey: '', // Explicitly cleared
  220. s3ReferenceFileWithRelayMode: true,
  221. gcsApiKeyJsonPath: '',
  222. gcsBucket: '',
  223. gcsUploadNamespace: '',
  224. gcsReferenceFileWithRelayMode: false,
  225. azureTenantId: '',
  226. azureClientId: '',
  227. azureClientSecret: '',
  228. azureStorageAccountName: '',
  229. azureStorageContainerName: '',
  230. azureReferenceFileWithRelayMode: false,
  231. };
  232. const dirtyFields = {
  233. s3Region: true,
  234. s3Bucket: true,
  235. s3AccessKeyId: true,
  236. s3SecretAccessKey: true, // Marked as dirty
  237. s3ReferenceFileWithRelayMode: true,
  238. };
  239. const requestParams = buildRequestParams(formData, dirtyFields);
  240. expect(requestParams).toHaveProperty('s3SecretAccessKey', '');
  241. });
  242. it('should NOT include Azure secret fields in request when they are not dirty', () => {
  243. const formData: FileUploadFormValues = {
  244. fileUploadType: 'azure',
  245. s3Region: '',
  246. s3CustomEndpoint: '',
  247. s3Bucket: '',
  248. s3AccessKeyId: '',
  249. s3SecretAccessKey: '',
  250. s3ReferenceFileWithRelayMode: false,
  251. gcsApiKeyJsonPath: '',
  252. gcsBucket: '',
  253. gcsUploadNamespace: '',
  254. gcsReferenceFileWithRelayMode: false,
  255. azureTenantId: '***existing-tenant***', // Not changed
  256. azureClientId: '***existing-client***', // Not changed
  257. azureClientSecret: '***existing-secret***', // Not changed
  258. azureStorageAccountName: 'new-account',
  259. azureStorageContainerName: 'new-container',
  260. azureReferenceFileWithRelayMode: true,
  261. };
  262. const dirtyFields = {
  263. azureStorageAccountName: true,
  264. azureStorageContainerName: true,
  265. azureReferenceFileWithRelayMode: true,
  266. // Azure secret fields are NOT marked as dirty
  267. };
  268. const requestParams = buildRequestParams(formData, dirtyFields);
  269. expect(requestParams).not.toHaveProperty('azureTenantId');
  270. expect(requestParams).not.toHaveProperty('azureClientId');
  271. expect(requestParams).not.toHaveProperty('azureClientSecret');
  272. expect(requestParams).toHaveProperty('azureStorageAccountName', 'new-account');
  273. expect(requestParams).toHaveProperty('azureStorageContainerName', 'new-container');
  274. });
  275. it('should include Azure secret fields in request when they are dirty', () => {
  276. const formData: FileUploadFormValues = {
  277. fileUploadType: 'azure',
  278. s3Region: '',
  279. s3CustomEndpoint: '',
  280. s3Bucket: '',
  281. s3AccessKeyId: '',
  282. s3SecretAccessKey: '',
  283. s3ReferenceFileWithRelayMode: false,
  284. gcsApiKeyJsonPath: '',
  285. gcsBucket: '',
  286. gcsUploadNamespace: '',
  287. gcsReferenceFileWithRelayMode: false,
  288. azureTenantId: 'new-tenant-id',
  289. azureClientId: 'new-client-id',
  290. azureClientSecret: 'new-client-secret',
  291. azureStorageAccountName: 'new-account',
  292. azureStorageContainerName: 'new-container',
  293. azureReferenceFileWithRelayMode: true,
  294. };
  295. const dirtyFields = {
  296. azureTenantId: true,
  297. azureClientId: true,
  298. azureClientSecret: true,
  299. azureStorageAccountName: true,
  300. azureStorageContainerName: true,
  301. azureReferenceFileWithRelayMode: true,
  302. };
  303. const requestParams = buildRequestParams(formData, dirtyFields);
  304. expect(requestParams).toEqual({
  305. fileUploadType: 'azure',
  306. azureTenantId: 'new-tenant-id',
  307. azureClientId: 'new-client-id',
  308. azureClientSecret: 'new-client-secret',
  309. azureStorageAccountName: 'new-account',
  310. azureStorageContainerName: 'new-container',
  311. azureReferenceFileWithRelayMode: true,
  312. });
  313. });
  314. it('should include only some Azure secret fields when only some are dirty', () => {
  315. const formData: FileUploadFormValues = {
  316. fileUploadType: 'azure',
  317. s3Region: '',
  318. s3CustomEndpoint: '',
  319. s3Bucket: '',
  320. s3AccessKeyId: '',
  321. s3SecretAccessKey: '',
  322. s3ReferenceFileWithRelayMode: false,
  323. gcsApiKeyJsonPath: '',
  324. gcsBucket: '',
  325. gcsUploadNamespace: '',
  326. gcsReferenceFileWithRelayMode: false,
  327. azureTenantId: 'new-tenant-id',
  328. azureClientId: '***existing-client***', // Not changed
  329. azureClientSecret: 'new-client-secret',
  330. azureStorageAccountName: 'new-account',
  331. azureStorageContainerName: 'new-container',
  332. azureReferenceFileWithRelayMode: true,
  333. };
  334. const dirtyFields = {
  335. azureTenantId: true, // Marked as dirty
  336. // azureClientId is NOT marked as dirty
  337. azureClientSecret: true, // Marked as dirty
  338. azureStorageAccountName: true,
  339. azureStorageContainerName: true,
  340. azureReferenceFileWithRelayMode: true,
  341. };
  342. const requestParams = buildRequestParams(formData, dirtyFields);
  343. expect(requestParams).toHaveProperty('azureTenantId', 'new-tenant-id');
  344. expect(requestParams).not.toHaveProperty('azureClientId');
  345. expect(requestParams).toHaveProperty('azureClientSecret', 'new-client-secret');
  346. });
  347. });