From 077935fad7f7e9b1cb5a339244271ce68b14b412 Mon Sep 17 00:00:00 2001 From: SmitGala Date: Fri, 27 Dec 2024 19:10:28 +0530 Subject: [PATCH] Remove ember-ajax and use ember-fetch --- app/adapters/file-report.ts | 8 +- app/authenticators/base.ts | 3 +- app/authenticators/irene.ts | 2 +- app/authenticators/saml2.ts | 36 +- .../personal-token-list/delete-token/index.ts | 3 +- .../personal-token-list/index.ts | 5 +- .../general/select-language/index.ts | 5 +- .../security/multi-factor-auth/index.ts | 26 +- .../security/password-change/index.ts | 5 +- .../override-form/index.ts | 1 - app/components/api-filter/index.ts | 3 +- .../version-table/actions/index.ts | 3 +- app/components/appknox-wrapper/index.ts | 1 - app/components/attachment-detail/index.ts | 11 +- .../index.ts | 3 +- .../api-scan/captured-apis/footer/index.ts | 3 +- .../api-scan/captured-apis/index.ts | 20 +- .../action/drawer/device-pref-table/index.ts | 3 +- .../dynamic-scan/action/drawer/index.ts | 3 +- .../file-details/dynamic-scan/action/index.ts | 3 +- .../dynamic-scan/drawer-old/index.ts | 3 +- .../dynamic-scan/results/index.ts | 1 - .../file-details/manual-scan/index.ts | 4 +- .../manual-scan/request-access/index.ts | 3 +- .../file-details/static-scan/index.ts | 7 +- .../file-details/summary/file-tags/index.ts | 3 +- .../edit-analysis-button/index.ts | 3 +- .../vulnerability-analysis/header/index.ts | 3 +- .../sbom-reports/sample/index.ts | 5 +- app/components/home-page/index.ts | 1 - .../app-scan-chart/index.ts | 3 +- .../organization-analytics/index.ts | 3 +- .../invoice-list/download-action/index.ts | 9 +- .../subscription/index.ts | 3 +- .../invite-delete/index.ts | 6 +- .../invite-resend/index.ts | 1 - .../organization-team/create-team/index.ts | 1 - .../project-preferences-old/provider/index.ts | 3 +- .../project-preferences/provider/index.ts | 3 +- .../toggle-analysis/index.ts | 3 +- .../vulnerability-list/index.ts | 7 +- .../dynamicscan-automation-settings/index.ts | 3 +- .../general-settings/github-project/index.ts | 3 +- .../project-settings/view-scenario/index.ts | 1 - app/components/public-api-docs/index.ts | 12 +- .../analysis-details/attachments/index.ts | 23 +- .../security/analysis-list/header/index.ts | 3 +- .../analysis-list/table/action/index.ts | 4 +- .../security/analysis-report-btn/index.ts | 22 +- app/components/security/download-app/index.ts | 3 +- .../security/file-details-actions/index.ts | 11 +- .../file-search-list/download/index.ts | 3 +- .../security/purge-api-analysis/index.ts | 3 +- app/components/system-status/index.ts | 24 +- app/components/user-login/index.ts | 40 +-- .../user-login/recover-password/index.ts | 5 +- .../user-login/reset-password/index.ts | 3 +- .../user-registration/via-login-page/index.ts | 20 +- .../user-registration/via-org-invite/index.ts | 6 +- .../via-partner-invite/index.ts | 7 +- .../dashboard/organization-settings/index.ts | 3 +- .../authenticated/github-cloud/redirect.ts | 12 +- app/routes/authenticated/payment-success.ts | 3 +- app/routes/invite.ts | 3 +- app/services/ajax.js | 42 --- app/services/ajax.ts | 314 ++++++++++++++++++ app/services/configuration.ts | 84 ++++- app/services/devicefarm.ts | 11 +- app/services/freshdesk.ts | 21 +- app/services/oidc.ts | 142 ++++---- app/services/organization.ts | 3 +- app/services/websocket.ts | 8 +- package-lock.json | 306 +---------------- package.json | 1 - .../file-details/manual-scan-test.js | 4 +- .../file-details/dynamic-scan/manual-test.js | 16 +- .../components/file-details/summary-test.js | 4 +- .../edit-analysis-button-test.js | 12 +- .../va-reports/report-item-test.js | 6 +- .../partner/client-report-download-test.js | 14 +- .../vulnerability-list/index-test.js | 7 +- .../index-test.js | 3 +- .../security/analysis-details-test.js | 7 +- .../user-login/recover-password-test.js | 8 +- .../components/via-org-invite-test.js | 12 +- .../components/via-partner-invite-test.js | 12 +- tests/unit/services/ajax-test.js | 91 ++++- tsconfig.json | 1 + 88 files changed, 888 insertions(+), 680 deletions(-) delete mode 100644 app/services/ajax.js create mode 100644 app/services/ajax.ts diff --git a/app/adapters/file-report.ts b/app/adapters/file-report.ts index c22c026d4..0ee965ed3 100644 --- a/app/adapters/file-report.ts +++ b/app/adapters/file-report.ts @@ -3,8 +3,6 @@ import { ModelSchema } from 'ember-data'; import commondrf from './commondrf'; import Store, { Snapshot } from '@ember-data/store'; import ModelRegistry from 'ember-data/types/registries/model'; -import NetworkService from 'irene/services/network'; -import { inject as service } from '@ember/service'; import { FileReportScanType } from 'irene/models/file-report'; interface FileReportQuery { @@ -18,8 +16,6 @@ enum REPORT_TYPE_ENDPOINT { } export default class FileReport extends commondrf { - @service declare network: NetworkService; - filesBaseUrl = this.buildURLFromBase(`${this.namespace_v2}/files`); reportsBaseUrl = this.buildURLFromBase(`${this.namespace_v2}/reports`); @@ -54,11 +50,11 @@ export default class FileReport extends commondrf { const reportTypeEndpoint = REPORT_TYPE_ENDPOINT[type]; const url = `${this.reportsBaseUrl}/${reportId}/${reportTypeEndpoint}`; - const response = await this.network.request(url, { + const response = await this.ajax(url, 'GET', { headers: this.headers, }); - return response.json() as { url?: string }; + return response as { url?: string }; } } diff --git a/app/authenticators/base.ts b/app/authenticators/base.ts index 90f75a77e..c6981c723 100644 --- a/app/authenticators/base.ts +++ b/app/authenticators/base.ts @@ -7,6 +7,7 @@ import RouterService from '@ember/routing/router-service'; import ENV from 'irene/config/environment'; import OidcService from 'irene/services/oidc'; import FreshdeskService from 'irene/services/freshdesk'; +import type IreneAjaxService from 'irene/services/ajax'; export interface LoginSuccessDataProps { token: string; @@ -35,7 +36,7 @@ export const processData = (data: LoginSuccessDataProps) => { }; export default class BaseAuthenticator extends Base { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare session: any; @service declare router: RouterService; @service('notifications') declare notify: NotificationService; diff --git a/app/authenticators/irene.ts b/app/authenticators/irene.ts index 7c47a3f2c..9057ea005 100644 --- a/app/authenticators/irene.ts +++ b/app/authenticators/irene.ts @@ -11,7 +11,7 @@ class IreneAuthenticator extends BaseAuthenticator { const url = ENV['ember-simple-auth']['loginEndPoint']; - return this.ajax.post(url, { data }).then((data: LoginSuccessDataProps) => { + return this.ajax.post(url, { data }).then((data) => { this.restoreLastTransition(data.user_id); return processData(data); diff --git a/app/authenticators/saml2.ts b/app/authenticators/saml2.ts index cdc666d04..8b42d6f99 100644 --- a/app/authenticators/saml2.ts +++ b/app/authenticators/saml2.ts @@ -4,28 +4,30 @@ import BaseAuthenticator, { LoginSuccessDataProps, processData } from './base'; export default class Saml2Auth extends BaseAuthenticator { authenticate(ssotoken: string) { return new Promise((resolve, reject) => { - const url = ENV['endpoints']['saml2Login']; + const url = ENV['endpoints']['saml2Login'] as string; - this.ajax.post(url, { data: { token: ssotoken } }).then( - (data: LoginSuccessDataProps) => { - this.restoreLastTransition(data.user_id); + this.ajax + .post(url, { data: { token: ssotoken } }) + .then( + (data) => { + this.restoreLastTransition(data.user_id); - data = processData(data); - resolve(data); - }, - (error: AjaxError) => { - let msg = 'Login failed'; + data = processData(data); + resolve(data); + }, + (error: AjaxError) => { + let msg = 'Login failed'; - if (error.payload.message) { - msg = 'Login failed: ' + error.payload.message; - } + if (error.payload.message) { + msg = 'Login failed: ' + error.payload.message; + } - this.notify.error(msg); - this.router.transitionTo('login'); + this.notify.error(msg); + this.router.transitionTo('login'); - return reject(msg); - } - ); + return reject(msg); + } + ); }); } } diff --git a/app/components/account-settings/developer-settings/personal-token-list/delete-token/index.ts b/app/components/account-settings/developer-settings/personal-token-list/delete-token/index.ts index e00485d08..5fb094912 100644 --- a/app/components/account-settings/developer-settings/personal-token-list/delete-token/index.ts +++ b/app/components/account-settings/developer-settings/personal-token-list/delete-token/index.ts @@ -7,6 +7,7 @@ import IntlService from 'ember-intl/services/intl'; import ENV from 'irene/config/environment'; import PersonaltokenModel from 'irene/models/personaltoken'; +import type IreneAjaxService from 'irene/services/ajax'; export interface AccountSettingsDeveloperSettingsPersonaltokenListDeleteTokenSignature { Args: { @@ -17,7 +18,7 @@ export interface AccountSettingsDeveloperSettingsPersonaltokenListDeleteTokenSig export default class AccountSettingsDeveloperSettingsPersonaltokenListDeleteTokenComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @tracked showRevokePersonalTokenConfirmBox = false; diff --git a/app/components/account-settings/developer-settings/personal-token-list/index.ts b/app/components/account-settings/developer-settings/personal-token-list/index.ts index 01ac49667..b7e320a7a 100644 --- a/app/components/account-settings/developer-settings/personal-token-list/index.ts +++ b/app/components/account-settings/developer-settings/personal-token-list/index.ts @@ -9,10 +9,11 @@ import { task } from 'ember-concurrency'; import { query } from 'ember-data-resources'; import PersonaltokenModel from 'irene/models/personaltoken'; +import type IreneAjaxService from 'irene/services/ajax'; export default class AccountSettingsDeveloperSettingsPersonaltokenListComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare store: Store; @service('notifications') declare notify: NotificationService; @@ -78,7 +79,7 @@ export default class AccountSettingsDeveloperSettingsPersonaltokenListComponent name: this.tokenName, }; - await this.ajax.post(ENV.endpoints['personaltokens'], { + await this.ajax.post(ENV.endpoints['personaltokens'] as string, { data, }); diff --git a/app/components/account-settings/general/select-language/index.ts b/app/components/account-settings/general/select-language/index.ts index 7951f8a00..23138366c 100644 --- a/app/components/account-settings/general/select-language/index.ts +++ b/app/components/account-settings/general/select-language/index.ts @@ -9,6 +9,7 @@ import type Store from '@ember-data/store'; import ENV from 'irene/config/environment'; import parseError from 'irene/utils/parse-error'; import type DatetimeService from 'irene/services/datetime'; +import type IreneAjaxService from 'irene/services/ajax'; const localeStrings = { en: 'English', @@ -19,7 +20,7 @@ type LocaleKeys = keyof typeof localeStrings; export default class AccountSettingsGeneralSelectLanguageComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare datetime: DatetimeService; @service declare session: any; @service declare store: Store; @@ -65,7 +66,7 @@ export default class AccountSettingsGeneralSelectLanguageComponent extends Compo }; try { - await this.ajax.post(ENV.endpoints['lang'], { data }); + await this.ajax.post(ENV.endpoints['lang'] as string, { data }); if (!this.isDestroyed) { window.location.reload(); diff --git a/app/components/account-settings/security/multi-factor-auth/index.ts b/app/components/account-settings/security/multi-factor-auth/index.ts index fa65cae87..538bdfcd0 100644 --- a/app/components/account-settings/security/multi-factor-auth/index.ts +++ b/app/components/account-settings/security/multi-factor-auth/index.ts @@ -15,14 +15,20 @@ import ENUMS from 'irene/enums'; import MeService from 'irene/services/me'; import MfaModel from 'irene/models/mfa'; import UserModel from 'irene/models/user'; +import type IreneAjaxService from 'irene/services/ajax'; type MfaConfirmEventData = { cancel: boolean; otp?: string }; +type TokenData = { + token: string; + secret: string; +}; + export default class AccountSettingsSecurityMultiFactorAuthComponent extends Component.extend( Evented ) { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare me: MeService; @service declare store: Store; @@ -169,7 +175,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com }); getMFAEnableEmailToken = task(async () => { - return await this.ajax.post(this.mfaEndpoint, { + return await this.ajax.post(this.mfaEndpoint, { data: { method: ENUMS.MFA_METHOD.HOTP, }, @@ -302,7 +308,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com }); getMFAEnableAppToken = task(async () => { - return await this.ajax.post(this.mfaEndpoint, { + return await this.ajax.post(this.mfaEndpoint, { data: { method: ENUMS.MFA_METHOD.TOTP, }, @@ -448,7 +454,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com verifySwitchToEmailAppOTP = task(async (otp) => { try { - return await this.ajax.post(this.mfaEndpoint, { + return await this.ajax.post(this.mfaEndpoint, { data: { method: ENUMS.MFA_METHOD.HOTP, otp: otp || '', @@ -517,7 +523,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com appOTPNotConfirmed = !(tokenData || {}).token; } while (appOTPNotConfirmed); - debug('SwitchTOEmail: App OTP Token Data ' + tokenData.token); + debug('SwitchTOEmail: App OTP Token Data ' + tokenData?.token); while (true) { debug('SwitchTOEmail: In Email OTP Loop'); @@ -529,7 +535,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com const confirmed = await this.verifySwitchToEmailEmailOTP.perform( emailOTPData.otp, - tokenData.token + tokenData?.token ); if (confirmed) { @@ -672,7 +678,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com } try { - return await this.ajax.post(this.mfaEndpoint, { + return await this.ajax.post(this.mfaEndpoint, { data: { method: ENUMS.MFA_METHOD.TOTP, otp: otp, @@ -733,7 +739,7 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com } let emailOTPNotConfirmed; - let tokenData; + let tokenData: TokenData; await this.staInitialEmail.perform(); @@ -745,7 +751,9 @@ export default class AccountSettingsSecurityMultiFactorAuthComponent extends Com return; } - tokenData = await this.staVerifyEmailOTP.perform(emailOTPData.otp); + tokenData = (await this.staVerifyEmailOTP.perform( + emailOTPData.otp + )) as TokenData; emailOTPNotConfirmed = !(tokenData || {}).token; } while (emailOTPNotConfirmed); diff --git a/app/components/account-settings/security/password-change/index.ts b/app/components/account-settings/security/password-change/index.ts index 9a22a1d35..82e64e5c6 100644 --- a/app/components/account-settings/security/password-change/index.ts +++ b/app/components/account-settings/security/password-change/index.ts @@ -14,6 +14,7 @@ import { Changeset } from 'ember-changeset'; import ENV from 'irene/config/environment'; import triggerAnalytics from 'irene/utils/trigger-analytics'; +import type IreneAjaxService from 'irene/services/ajax'; type ChangesetBufferProps = BufferedChangeset & { old_password: string; @@ -29,7 +30,7 @@ const ChangeValidator = { export default class AccountSettingsSecurityPasswordChangeComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('rollbar') declare logger: any; @service declare router: RouterService; @service('notifications') declare notify: NotificationService; @@ -63,7 +64,7 @@ export default class AccountSettingsSecurityPasswordChangeComponent extends Comp }; try { - await this.ajax.post(this.changePasswordURL, { + await this.ajax.post(String(this.changePasswordURL), { data, }); diff --git a/app/components/analysis-risk/override-edit-drawer/override-form/index.ts b/app/components/analysis-risk/override-edit-drawer/override-form/index.ts index 0be103269..3c0dc0f43 100644 --- a/app/components/analysis-risk/override-edit-drawer/override-form/index.ts +++ b/app/components/analysis-risk/override-edit-drawer/override-form/index.ts @@ -44,7 +44,6 @@ type RiskOverrideCriteria = { label: string; value: string }; export default class AnalysisRiskOverrideEditDrawerOverrideFormComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; @service('notifications') declare notify: NotificationService; @tracked showOverrideSuccess = false; diff --git a/app/components/api-filter/index.ts b/app/components/api-filter/index.ts index 6b9113c3e..d1861b8db 100644 --- a/app/components/api-filter/index.ts +++ b/app/components/api-filter/index.ts @@ -10,6 +10,7 @@ import triggerAnalytics from 'irene/utils/trigger-analytics'; import ApiScanOptionsModel from 'irene/models/api-scan-options'; import { task } from 'ember-concurrency'; import { action } from '@ember/object'; +import type IreneAjaxService from 'irene/services/ajax'; const isRegexFailed = function (url: string) { const reg = @@ -29,7 +30,7 @@ export interface ApiFilterSignature { export default class ApiFilterComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare store: Store; @service('notifications') declare notify: NotificationService; diff --git a/app/components/app-monitoring/version-table/actions/index.ts b/app/components/app-monitoring/version-table/actions/index.ts index 6897918e6..395285763 100644 --- a/app/components/app-monitoring/version-table/actions/index.ts +++ b/app/components/app-monitoring/version-table/actions/index.ts @@ -17,6 +17,7 @@ import parseError from 'irene/utils/parse-error'; import SubmissionModel from 'irene/models/submission'; import RealtimeService from 'irene/services/realtime'; import ENUMS from 'irene/enums'; +import type IreneAjaxService from 'irene/services/ajax'; dayjs.extend(advancedFormat); @@ -27,7 +28,7 @@ interface AppMonitoringVersionTableActionsSignature { } export default class AppMonitoringVersionTableActionsComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare store: Store; @service declare intl: IntlService; diff --git a/app/components/appknox-wrapper/index.ts b/app/components/appknox-wrapper/index.ts index 17ba472c0..ef2fb4eaa 100644 --- a/app/components/appknox-wrapper/index.ts +++ b/app/components/appknox-wrapper/index.ts @@ -26,7 +26,6 @@ export interface AppknoxWrapperSignature { } export default class AppknoxWrapperComponent extends Component { - @service declare ajax: any; @service declare session: any; @service declare me: MeService; @service declare intl: IntlService; diff --git a/app/components/attachment-detail/index.ts b/app/components/attachment-detail/index.ts index 9ab63e5cf..424a32298 100644 --- a/app/components/attachment-detail/index.ts +++ b/app/components/attachment-detail/index.ts @@ -3,6 +3,7 @@ import { inject as service } from '@ember/service'; import ENV from 'irene/config/environment'; import AttachmentModel from 'irene/models/attachment'; import { task } from 'ember-concurrency'; +import type IreneAjaxService from 'irene/services/ajax'; export interface AttachmentDetailSignature { Args: { @@ -10,8 +11,14 @@ export interface AttachmentDetailSignature { }; } +interface DownloadResponse { + data: { + url: string; + }; +} + export default class AttachmentDetailComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service('browser/window') declare window: Window; @@ -19,7 +26,7 @@ export default class AttachmentDetailComponent extends Component(url); this.window.open(result.data.url); } catch (error) { diff --git a/app/components/dynamicscan-automation-upselling-feature/index.ts b/app/components/dynamicscan-automation-upselling-feature/index.ts index a99bbb99d..917086aa0 100644 --- a/app/components/dynamicscan-automation-upselling-feature/index.ts +++ b/app/components/dynamicscan-automation-upselling-feature/index.ts @@ -6,9 +6,10 @@ import { inject as service } from '@ember/service'; import type IntlService from 'ember-intl/services/intl'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; export default class DyanmicscanAutomationUpsellingFeatureComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare intl: IntlService; @service('notifications') declare notify: NotificationService; @service('browser/window') declare window: Window; diff --git a/app/components/file-details/api-scan/captured-apis/footer/index.ts b/app/components/file-details/api-scan/captured-apis/footer/index.ts index c394cb085..6db82e52f 100644 --- a/app/components/file-details/api-scan/captured-apis/footer/index.ts +++ b/app/components/file-details/api-scan/captured-apis/footer/index.ts @@ -9,6 +9,7 @@ import ENV from 'irene/config/environment'; import triggerAnalytics from 'irene/utils/trigger-analytics'; import parseError from 'irene/utils/parse-error'; import type FileModel from 'irene/models/file'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsApiScanCapturedApisFooterSignature { Args: { @@ -18,7 +19,7 @@ export interface FileDetailsApiScanCapturedApisFooterSignature { } export default class FileDetailsApiScanCapturedApisFooterComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare intl: IntlService; @service('notifications') declare notify: NotificationService; diff --git a/app/components/file-details/api-scan/captured-apis/index.ts b/app/components/file-details/api-scan/captured-apis/index.ts index e62e50ab4..d145623e9 100644 --- a/app/components/file-details/api-scan/captured-apis/index.ts +++ b/app/components/file-details/api-scan/captured-apis/index.ts @@ -14,6 +14,7 @@ import type { PaginationProviderActionsArgs } from 'irene/components/ak-paginati import type FileModel from 'irene/models/file'; import type CapturedApiModel from 'irene/models/capturedapi'; import type ApiScanService from 'irene/services/api-scan'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsApiScanCapturedApisSignature { Args: { @@ -26,9 +27,14 @@ type CapturedApiQueryResponse = meta: { count: number }; }; +type SelectAPIResponse = { + count: number; + results: []; +}; + export default class FileDetailsApiScanCapturedApisComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare store: Store; @service declare apiScan: ApiScanService; @service('notifications') declare notify: NotificationService; @@ -96,14 +102,20 @@ export default class FileDetailsApiScanCapturedApisComponent extends Component { try { - const selectedApis = await this.getSelectedApis.perform(); + const selectedApis = + (await this.getSelectedApis.perform()) as SelectAPIResponse; this.selectedCount = selectedApis.count; diff --git a/app/components/file-details/dynamic-scan/action/drawer/device-pref-table/index.ts b/app/components/file-details/dynamic-scan/action/drawer/device-pref-table/index.ts index 2083fcbe8..6317e4c57 100644 --- a/app/components/file-details/dynamic-scan/action/drawer/device-pref-table/index.ts +++ b/app/components/file-details/dynamic-scan/action/drawer/device-pref-table/index.ts @@ -13,6 +13,7 @@ import type IntlService from 'ember-intl/services/intl'; import type Store from '@ember-data/store'; import styles from './index.scss'; +import type IreneAjaxService from 'irene/services/ajax'; enum AvailableManualDeviceModelKeyMap { ALL_AVAILABLE_DEVICES = 'all', @@ -35,7 +36,7 @@ export interface FileDetailsDynamicScanDrawerDevicePrefTableSignature { export default class FileDetailsDynamicScanDrawerDevicePrefTableComponent extends Component { @service declare store: Store; @service('notifications') declare notify: NotificationService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare intl: IntlService; @tracked limit = 5; diff --git a/app/components/file-details/dynamic-scan/action/drawer/index.ts b/app/components/file-details/dynamic-scan/action/drawer/index.ts index 30cf53d18..43dcd84dd 100644 --- a/app/components/file-details/dynamic-scan/action/drawer/index.ts +++ b/app/components/file-details/dynamic-scan/action/drawer/index.ts @@ -17,6 +17,7 @@ import type Store from '@ember-data/store'; import type FileModel from 'irene/models/file'; import { type DevicePreferenceContext } from 'irene/components/project-preferences/provider'; import type ProjectAvailableDeviceModel from 'irene/models/project-available-device'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsDynamicScanActionDrawerSignature { Args: { @@ -30,7 +31,7 @@ export interface FileDetailsDynamicScanActionDrawerSignature { export default class FileDetailsDynamicScanActionDrawerComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare store: Store; @service('notifications') declare notify: NotificationService; diff --git a/app/components/file-details/dynamic-scan/action/index.ts b/app/components/file-details/dynamic-scan/action/index.ts index 965f5a987..dceb2e7d7 100644 --- a/app/components/file-details/dynamic-scan/action/index.ts +++ b/app/components/file-details/dynamic-scan/action/index.ts @@ -11,6 +11,7 @@ import type FileModel from 'irene/models/file'; import type PollService from 'irene/services/poll'; import type DynamicscanModel from 'irene/models/dynamicscan'; import type { DevicePreferenceContext } from 'irene/components/project-preferences-old/provider'; +import type IreneAjaxService from 'irene/services/ajax'; export interface DynamicScanActionSignature { Args: { @@ -24,7 +25,7 @@ export interface DynamicScanActionSignature { } export default class DynamicScanActionComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare poll: PollService; @service('browser/window') declare window: Window; diff --git a/app/components/file-details/dynamic-scan/drawer-old/index.ts b/app/components/file-details/dynamic-scan/drawer-old/index.ts index 3793ed6bd..3e38e382a 100644 --- a/app/components/file-details/dynamic-scan/drawer-old/index.ts +++ b/app/components/file-details/dynamic-scan/drawer-old/index.ts @@ -11,6 +11,7 @@ import ENUMS from 'irene/enums'; import triggerAnalytics from 'irene/utils/trigger-analytics'; import type FileModel from 'irene/models/file'; import type { DevicePreferenceContext } from 'irene/components/project-preferences-old/provider'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsDynamicScanDrawerOldSignature { Args: { @@ -23,7 +24,7 @@ export interface FileDetailsDynamicScanDrawerOldSignature { export default class FileDetailsDynamicScanDrawerOldComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare store: Store; @service('browser/window') declare window: Window; @service('notifications') declare notify: NotificationService; diff --git a/app/components/file-details/dynamic-scan/results/index.ts b/app/components/file-details/dynamic-scan/results/index.ts index 393e1b600..15e253a74 100644 --- a/app/components/file-details/dynamic-scan/results/index.ts +++ b/app/components/file-details/dynamic-scan/results/index.ts @@ -17,7 +17,6 @@ export interface FileDetailsDastResultsSignature { export default class FileDetailsDastResults extends Component { @service declare intl: IntlService; @service('notifications') declare notify: NotificationService; - @service declare ajax: any; @tracked sorts: EmberTableSort[] = [ { isAscending: false, valuePath: 'computedRisk' }, diff --git a/app/components/file-details/manual-scan/index.ts b/app/components/file-details/manual-scan/index.ts index 6b822a8ad..e66ac22c6 100644 --- a/app/components/file-details/manual-scan/index.ts +++ b/app/components/file-details/manual-scan/index.ts @@ -11,6 +11,7 @@ import ENV from 'irene/config/environment'; import type FileModel from 'irene/models/file'; import type ManualscanModel from 'irene/models/manualscan'; import type OrganizationService from 'irene/services/organization'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsManualScanSignature { Args: { @@ -23,7 +24,7 @@ export interface FileDetailsManualScanSignature { export default class FileDetailsManualScanComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare organization: OrganizationService; @service declare store: Store; @service('notifications') declare notify: NotificationService; @@ -150,7 +151,6 @@ export default class FileDetailsManualScanComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare organization: OrganizationService; @service('notifications') declare notify: NotificationService; diff --git a/app/components/file-details/static-scan/index.ts b/app/components/file-details/static-scan/index.ts index 937b41b7f..fd2fd3aae 100644 --- a/app/components/file-details/static-scan/index.ts +++ b/app/components/file-details/static-scan/index.ts @@ -9,6 +9,7 @@ import type { EmberTableSort } from 'ember-table'; import ENUMS from 'irene/enums'; import ENV from 'irene/config/environment'; import type FileModel from 'irene/models/file'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsStaticScanSignature { Args: { @@ -19,7 +20,7 @@ export interface FileDetailsStaticScanSignature { export default class FileDetailsStaticScan extends Component { @service declare intl: IntlService; @service('notifications') declare notify: NotificationService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked showRescanModal = false; @@ -92,9 +93,7 @@ export default class FileDetailsStaticScan extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @tracked showAddTagForm = false; diff --git a/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.ts b/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.ts index 82183bc75..349a5fac1 100644 --- a/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.ts +++ b/app/components/file-details/vulnerability-analysis-details/edit-analysis-button/index.ts @@ -9,6 +9,7 @@ import ENV from 'irene/config/environment'; import ENUMS from 'irene/enums'; import MeService from 'irene/services/me'; import AnalysisModel from 'irene/models/analysis'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsVulnerabilityAnalysisDetailsEditAnalysisButtonSignature { Args: { @@ -19,7 +20,7 @@ export interface FileDetailsVulnerabilityAnalysisDetailsEditAnalysisButtonSignat export default class FileDetailsVulnerabilityAnalysisDetailsEditAnalysisButtonComponent extends Component { @service declare me: MeService; @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked showEditAnalysisDrawer = false; @tracked showResetAnalysisConfirmBox = false; diff --git a/app/components/file-details/vulnerability-analysis/header/index.ts b/app/components/file-details/vulnerability-analysis/header/index.ts index bed45226f..dd9fad1e4 100644 --- a/app/components/file-details/vulnerability-analysis/header/index.ts +++ b/app/components/file-details/vulnerability-analysis/header/index.ts @@ -6,6 +6,7 @@ import { inject as service } from '@ember/service'; import ENUMS from 'irene/enums'; import styles from './index.scss'; import type FileModel from 'irene/models/file'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsVulnerabilityAnalysisHeaderSignature { Args: { @@ -16,7 +17,7 @@ export interface FileDetailsVulnerabilityAnalysisHeaderSignature { } export default class FileDetailsVulnerabilityAnalysisHeaderComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked isSecurityEnabled = false; diff --git a/app/components/file/report-drawer/sbom-reports/sample/index.ts b/app/components/file/report-drawer/sbom-reports/sample/index.ts index f70034639..5e32e79c3 100644 --- a/app/components/file/report-drawer/sbom-reports/sample/index.ts +++ b/app/components/file/report-drawer/sbom-reports/sample/index.ts @@ -8,9 +8,9 @@ import { task } from 'ember-concurrency'; import Store from '@ember-data/store'; import { waitForPromise } from '@ember/test-waiters'; -import NetworkService from 'irene/services/network'; import SbomReportModel, { SbomReportType } from 'irene/models/sbom-report'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; type SbomScanReportQueryResponse = DS.AdapterPopulatedRecordArray & { @@ -18,8 +18,7 @@ type SbomScanReportQueryResponse = }; export default class FileReportDrawerSbomReportsSampleComponent extends Component { - @service declare ajax: any; - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service declare store: Store; @service declare intl: IntlService; @service('notifications') declare notify: NotificationService; diff --git a/app/components/home-page/index.ts b/app/components/home-page/index.ts index f1058ccd2..e174e4066 100644 --- a/app/components/home-page/index.ts +++ b/app/components/home-page/index.ts @@ -26,7 +26,6 @@ export default class HomePageComponent extends Component { @service declare organization: OrganizationService; @service declare userAuth: UserAuthService; @service declare session: any; - @service declare ajax: any; @service declare whitelabel: WhitelabelService; get isStoreknoxEnabled() { diff --git a/app/components/organization-analytics/app-scan-chart/index.ts b/app/components/organization-analytics/app-scan-chart/index.ts index 34ff69ae2..7900ffb62 100644 --- a/app/components/organization-analytics/app-scan-chart/index.ts +++ b/app/components/organization-analytics/app-scan-chart/index.ts @@ -16,6 +16,7 @@ import { CalendarOnSelectFunc, RangeDateObject, } from 'irene/components/ak-date-picker'; +import type IreneAjaxService from 'irene/services/ajax'; export interface IAppScanResult { created_on_date: string; @@ -43,7 +44,7 @@ interface AppScanDataItemGroup { } export default class OrganizationAnalyticsAppScanChartComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare organization: OrganizationService; @service('notifications') declare notify: NotificationService; diff --git a/app/components/organization-analytics/index.ts b/app/components/organization-analytics/index.ts index 2e586f206..7b3a7a850 100644 --- a/app/components/organization-analytics/index.ts +++ b/app/components/organization-analytics/index.ts @@ -5,6 +5,7 @@ import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import OrganizationService from 'irene/services/organization'; +import type IreneAjaxService from 'irene/services/ajax'; export interface IScanCount { api_scan_count: number; @@ -18,7 +19,7 @@ export interface IScanCount { } export default class OrganizationAnalyticsComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare organization: OrganizationService; @tracked scanCount: IScanCount | null = null; diff --git a/app/components/organization-billing/invoice-list/download-action/index.ts b/app/components/organization-billing/invoice-list/download-action/index.ts index bd5ad6084..8945b51bb 100644 --- a/app/components/organization-billing/invoice-list/download-action/index.ts +++ b/app/components/organization-billing/invoice-list/download-action/index.ts @@ -4,6 +4,7 @@ import { task } from 'ember-concurrency'; import ENV from 'irene/config/environment'; import type InvoiceModel from 'irene/models/invoice'; +import type IreneAjaxService from 'irene/services/ajax'; interface OrganizationBillingInvoiceListDownloadActionSignature { Args: { @@ -11,8 +12,12 @@ interface OrganizationBillingInvoiceListDownloadActionSignature { }; } +type DownloadURLResponse = { + url: string; +}; + export default class OrganizationBillingInvoiceListDownloadActionComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('browser/window') declare window: Window; @service('notifications') declare notify: NotificationService; @@ -21,7 +26,7 @@ export default class OrganizationBillingInvoiceListDownloadActionComponent exten const url = new URL(downloadUrl, ENV.host).href; try { - const result = await this.ajax.request(url); + const result = await this.ajax.request(url); if (!this.isDestroyed) { this.window.location.href = result.url; diff --git a/app/components/organization-billing/subscription/index.ts b/app/components/organization-billing/subscription/index.ts index 0d4b16625..fb9f8dca5 100644 --- a/app/components/organization-billing/subscription/index.ts +++ b/app/components/organization-billing/subscription/index.ts @@ -7,6 +7,7 @@ import type IntlService from 'ember-intl/services/intl'; import ENV from 'irene/config/environment'; import type SubscriptionModel from 'irene/models/subscription'; +import type IreneAjaxService from 'irene/services/ajax'; interface OrganizationBillingSubscriptionSignature { Args: { @@ -16,7 +17,7 @@ interface OrganizationBillingSubscriptionSignature { export default class OrganizationBillingSubscriptionComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @tracked showCancelSubscriptionConfirmBox = false; diff --git a/app/components/organization-invitation-list/invite-delete/index.ts b/app/components/organization-invitation-list/invite-delete/index.ts index 38f49e355..26d1c941e 100644 --- a/app/components/organization-invitation-list/invite-delete/index.ts +++ b/app/components/organization-invitation-list/invite-delete/index.ts @@ -2,10 +2,11 @@ import Component from '@glimmer/component'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; import { task } from 'ember-concurrency'; -import ENV from 'irene/config/environment'; -import triggerAnalytics from 'irene/utils/trigger-analytics'; import { tracked } from '@glimmer/tracking'; import IntlService from 'ember-intl/services/intl'; + +import ENV from 'irene/config/environment'; +import triggerAnalytics from 'irene/utils/trigger-analytics'; import OrganizationInvitationModel from 'irene/models/organization-invitation'; import OrganizationTeamInvitationModel from 'irene/models/organization-team-invitation'; @@ -20,7 +21,6 @@ interface OrganizationMemberInvitationListInviteDeleteSignature { export default class OrganizationMemberInvitationListInviteDelete extends Component { @service declare intl: IntlService; - @service declare ajax: any; @service('notifications') declare notify: NotificationService; @tracked isDeletingInvitation = false; diff --git a/app/components/organization-invitation-list/invite-resend/index.ts b/app/components/organization-invitation-list/invite-resend/index.ts index 252808ded..cfe10089f 100644 --- a/app/components/organization-invitation-list/invite-resend/index.ts +++ b/app/components/organization-invitation-list/invite-resend/index.ts @@ -22,7 +22,6 @@ interface OrganizationInvitationListInviteResendSignature { export default class OrganizationInvitationListInviteResend extends Component { @service declare intl: IntlService; - @service declare ajax: any; @service('notifications') declare notify: NotificationService; @tracked isResendingInvitation = false; diff --git a/app/components/organization-team/create-team/index.ts b/app/components/organization-team/create-team/index.ts index a709ca190..df2fd0169 100644 --- a/app/components/organization-team/create-team/index.ts +++ b/app/components/organization-team/create-team/index.ts @@ -23,7 +23,6 @@ export default class OrganizationTeamCreateTeam extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare store: Store; diff --git a/app/components/project-preferences/provider/index.ts b/app/components/project-preferences/provider/index.ts index 791d595b6..0a3ea41c2 100644 --- a/app/components/project-preferences/provider/index.ts +++ b/app/components/project-preferences/provider/index.ts @@ -23,6 +23,7 @@ import ProfileModel, { type ProfileDSAutomatedDevicePrefData, type ProfileDSManualDevicePrefData, } from 'irene/models/profile'; +import type IreneAjaxService from 'irene/services/ajax'; type ProfileDsSelectFuncHandler = (option: { value: number }) => void; @@ -67,7 +68,7 @@ type DeviceType = EnumObject; export default class ProjectPreferencesProviderComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare store: Store; diff --git a/app/components/project-settings/analysis-settings/toggle-analysis/index.ts b/app/components/project-settings/analysis-settings/toggle-analysis/index.ts index 0e680ad78..926b086d4 100644 --- a/app/components/project-settings/analysis-settings/toggle-analysis/index.ts +++ b/app/components/project-settings/analysis-settings/toggle-analysis/index.ts @@ -9,6 +9,7 @@ import Store from '@ember-data/store'; import UnknownAnalysisStatusModel from 'irene/models/unknown-analysis-status'; import { task } from 'ember-concurrency'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; interface ProjectSettingsAnalysisSettingsToggleAnalysisSignature { Args: { @@ -18,7 +19,7 @@ interface ProjectSettingsAnalysisSettingsToggleAnalysisSignature { export default class ProjectSettingsAnalysisSettingsToggleAnalysisComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare store: Store; diff --git a/app/components/project-settings/analysis-settings/vulnerability-list/index.ts b/app/components/project-settings/analysis-settings/vulnerability-list/index.ts index 5d355e36f..d48f14fe6 100644 --- a/app/components/project-settings/analysis-settings/vulnerability-list/index.ts +++ b/app/components/project-settings/analysis-settings/vulnerability-list/index.ts @@ -15,6 +15,7 @@ import ProjectModel from 'irene/models/project'; import VulnerabilityPreferenceModel from 'irene/models/vulnerability-preference'; import MeService from 'irene/services/me'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; type ProjectSettingsAnalysisSettingsVulnerabilityListQueryResponse = DS.AdapterPopulatedRecordArray & { @@ -31,7 +32,7 @@ export default class ProjectSettingsAnalysisSettingsVulnerabilityListComponent e @service declare me: MeService; @service declare store: Store; @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @tracked @@ -180,7 +181,9 @@ export default class ProjectSettingsAnalysisSettingsVulnerabilityListComponent e vulnerabilityId, ].join('/'); - const res = await this.ajax.put(url, { data }); + const res = await this.ajax.put(url, { + data, + }); // update model this.selectedVulnerabilityPreference?.updateValues(res); diff --git a/app/components/project-settings/general-settings/dynamicscan-automation-settings/index.ts b/app/components/project-settings/general-settings/dynamicscan-automation-settings/index.ts index 21a1f8cc6..13ac12499 100644 --- a/app/components/project-settings/general-settings/dynamicscan-automation-settings/index.ts +++ b/app/components/project-settings/general-settings/dynamicscan-automation-settings/index.ts @@ -9,6 +9,7 @@ import { waitForPromise } from '@ember/test-waiters'; import ENV from 'irene/config/environment'; import ProjectModel from 'irene/models/project'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; export interface ProjectSettingsGeneralSettingsDyanmicscanAutomationSettingsSignature { Args: { @@ -21,7 +22,7 @@ export interface ProjectSettingsGeneralSettingsDyanmicscanAutomationSettingsSign export default class ProjectSettingsGeneralSettingsDyanmicscanAutomationSettingsComponent extends Component { @service declare store: Store; @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @tracked automationEnabled = false; diff --git a/app/components/project-settings/general-settings/github-project/index.ts b/app/components/project-settings/general-settings/github-project/index.ts index bfd0eac0b..688b1f62f 100644 --- a/app/components/project-settings/general-settings/github-project/index.ts +++ b/app/components/project-settings/general-settings/github-project/index.ts @@ -12,6 +12,7 @@ import OrganizationService from 'irene/services/organization'; import ProjectModel from 'irene/models/project'; import GithubRepoModel, { GithubRepoDetails } from 'irene/models/github-repo'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; export interface ProjectSettingsGeneralSettingsGithubProjectSignature { Args: { @@ -23,7 +24,7 @@ export default class ProjectSettingsGeneralSettingsGithubProjectComponent extend @service declare intl: IntlService; @service declare store: Store; @service('notifications') declare notify: NotificationService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare organization: OrganizationService; @tracked currentGithubRepo: GithubRepoModel | null = null; diff --git a/app/components/project-settings/view-scenario/index.ts b/app/components/project-settings/view-scenario/index.ts index 77ce951f6..aa049faf0 100644 --- a/app/components/project-settings/view-scenario/index.ts +++ b/app/components/project-settings/view-scenario/index.ts @@ -25,7 +25,6 @@ export default class ProjectSettingsViewScenarioComponent extends Component >; export default class PublicApiDocsComponent extends Component { - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service declare intl: IntlService; @service declare me: MeService; @service('notifications') declare notify: NotificationService; @@ -78,15 +78,11 @@ export default class PublicApiDocsComponent extends Component { fetchSchemaData = task(async () => { try { - const res = await waitForPromise( - this.network.request('/api/public_api/schema', { + this.data = await waitForPromise( + this.ajax.request('/api/public_api/schema', { headers: { accept: 'application/json, */*' }, }) ); - - const data = (await waitForPromise(res.json())) as SwaggerUIDataProps; - - this.data = data; } catch (error) { this.notify.error(parseError(error, this.intl.t('pleaseTryAgain'))); } diff --git a/app/components/security/analysis-details/attachments/index.ts b/app/components/security/analysis-details/attachments/index.ts index 0ba0c2f65..0c75fac6f 100644 --- a/app/components/security/analysis-details/attachments/index.ts +++ b/app/components/security/analysis-details/attachments/index.ts @@ -11,6 +11,7 @@ import { type UploadFile } from 'ember-file-upload'; import type IntlService from 'ember-intl/services/intl'; import type Store from '@ember-data/store'; import type SecurityAnalysisModel from 'irene/models/security/analysis'; +import type IreneAjaxService from 'irene/services/ajax'; export interface SecurityAnalysisDetailsAttachmentsComponentSignature { Args: { @@ -19,12 +20,19 @@ export interface SecurityAnalysisDetailsAttachmentsComponentSignature { }; } +type UploadAttachmentResponse = { + file_key: string; + file_key_signed: string; + file_uuid: string; + url: string; +}; + export default class SecurityAnalysisDetailsAttachmentsComponent extends Component { @service declare store: Store; @service('browser/window') declare window: Window; @service declare notifications: NotificationService; @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked showRemoveFileConfirmBox = false; @tracked fileIDToDelete: string | null = null; @@ -99,10 +107,13 @@ export default class SecurityAnalysisDetailsAttachmentsComponent extends Compone }; try { - const fileData = await this.ajax.post(ENV.endpoints['uploadFile'], { - namespace: 'api/hudson-api', - data, - }); + const fileData = await this.ajax.post( + ENV.endpoints['uploadFile'] as string, + { + namespace: 'api/hudson-api', + data, + } + ); await file.uploadBinary(fileData.url, { method: 'PUT', @@ -117,7 +128,7 @@ export default class SecurityAnalysisDetailsAttachmentsComponent extends Compone content_type: 'ANALYSIS', }; - await this.ajax.post(ENV.endpoints['uploadedAttachment'], { + await this.ajax.post(ENV.endpoints['uploadedAttachment'] as string, { namespace: 'api/hudson-api', data: fileDetailsData, }); diff --git a/app/components/security/analysis-list/header/index.ts b/app/components/security/analysis-list/header/index.ts index 685d01928..564c1758b 100644 --- a/app/components/security/analysis-list/header/index.ts +++ b/app/components/security/analysis-list/header/index.ts @@ -18,6 +18,7 @@ import type { Owner } from '@ember/test-helpers/build-owner'; import type SecurityFileModel from 'irene/models/security/file'; import type VulnerabilityModel from 'irene/models/vulnerability'; +import type IreneAjaxService from 'irene/services/ajax'; type VulnerabilityQueryResponse = DS.AdapterPopulatedRecordArray & { @@ -39,7 +40,7 @@ export default class SecurityAnalysisListHeaderComponent extends Component { @service('notifications') declare notify: NotificationService; @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked showMarkPassedConfirmBox = false; @@ -61,7 +62,6 @@ export default class SecurityAnalysisListTableActionComponent extends Component< await this.ajax.put(url, { namespace: 'api/hudson-api', - contentType: 'application/json', data: JSON.stringify({ ...this.PASSED_STATE, owasp: (await this.analysis.owasp).map((a) => a.get('id')), diff --git a/app/components/security/analysis-report-btn/index.ts b/app/components/security/analysis-report-btn/index.ts index 6a03426c8..5c74e007e 100644 --- a/app/components/security/analysis-report-btn/index.ts +++ b/app/components/security/analysis-report-btn/index.ts @@ -10,6 +10,7 @@ import ENV from 'irene/config/environment'; import type IntlService from 'ember-intl/services/intl'; import type SecurityFileModel from 'irene/models/security/file'; +import type IreneAjaxService from 'irene/services/ajax'; export interface SecurityFileAnalysisReportBtnSignature { Element: HTMLElement; @@ -18,11 +19,23 @@ export interface SecurityFileAnalysisReportBtnSignature { }; } +type DownloadReportsResponse = { + xlsx: string; + html_en: string; + html_ja: string; +}; + +type DownloadReportType = { + label: string; + format: keyof DownloadReportsResponse; + icon: string; +}; + export default class SecurityFileAnalysisReportBtnComponent extends Component { @service declare intl: IntlService; @service('notifications') declare notify: NotificationService; @service('browser/window') declare window: Window; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked isShowGenerateReportModal = false; @tracked emailsToSend = ''; @@ -115,7 +128,6 @@ export default class SecurityFileAnalysisReportBtnComponent extends Component { + downloadReport = task(async (type: DownloadReportType) => { try { const url = [ENV.endpoints['reports'], this.fileId, 'download_url'].join( '/' ); - const data = await this.ajax.request(url, { + const data = (await this.ajax.request(url, { namespace: 'api/hudson-api', - }); + })) as DownloadReportsResponse; if (data && data[type.format]) { this.window.open(data[type.format], '_blank'); diff --git a/app/components/security/download-app/index.ts b/app/components/security/download-app/index.ts index 99335b3dc..7954c5c22 100644 --- a/app/components/security/download-app/index.ts +++ b/app/components/security/download-app/index.ts @@ -4,10 +4,11 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { task } from 'ember-concurrency'; import ENV from 'irene/config/environment'; +import type IreneAjaxService from 'irene/services/ajax'; import parseError from 'irene/utils/parse-error'; export default class SecurityDownloadAppComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service('browser/window') declare window: Window; diff --git a/app/components/security/file-details-actions/index.ts b/app/components/security/file-details-actions/index.ts index 5cc33f912..170bda007 100644 --- a/app/components/security/file-details-actions/index.ts +++ b/app/components/security/file-details-actions/index.ts @@ -11,6 +11,7 @@ import parseError from 'irene/utils/parse-error'; import type IntlService from 'ember-intl/services/intl'; import type Store from '@ember-data/store'; import type SecurityFileModel from 'irene/models/security/file'; +import type IreneAjaxService from 'irene/services/ajax'; export interface FileDetailsActionsSignature { Element: HTMLElement; @@ -19,12 +20,16 @@ export interface FileDetailsActionsSignature { }; } +type DownloadAppResponse = { + url: string; +}; + export default class FileDetailsActionsComponent extends Component { @service declare intl: IntlService; @service declare store: Store; @service declare notifications: NotificationService; @service('browser/window') declare window: Window; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; get packageName() { return this.file.project.get('packageName'); @@ -173,7 +178,7 @@ export default class FileDetailsActionsComponent extends Component(url, { namespace: 'api/hudson-api', }); @@ -195,7 +200,7 @@ export default class FileDetailsActionsComponent extends Component { const url = [ENV.endpoints['apps'], this.fileId, 'modified'].join('/'); - const data = await this.ajax.request(url, { + const data = await this.ajax.request(url, { namespace: 'api/hudson-api', }); diff --git a/app/components/security/file-search-list/download/index.ts b/app/components/security/file-search-list/download/index.ts index 83597dfbc..11cda7e84 100644 --- a/app/components/security/file-search-list/download/index.ts +++ b/app/components/security/file-search-list/download/index.ts @@ -7,6 +7,7 @@ import IntlService from 'ember-intl/services/intl'; import SecurityFileModel from 'irene/models/security/file'; import ENV from 'irene/config/environment'; import parseError from 'irene/utils/parse-error'; +import type IreneAjaxService from 'irene/services/ajax'; export interface SecurityFileSearchListDownloadComponentSignature { Args: { @@ -18,7 +19,7 @@ export default class SecurityFileSearchListDownloadComponent extends Component { try { - const status = await this.ajax.request(ENV.endpoints['status']); + const status = await this.ajax.request( + ENV.endpoints['status'] as string + ); await this.ajax.request(status.data.storage, { headers: {} }); - } catch (error) { - this.isStorageWorking = !!isNotFoundError(error as AjaxError); + } catch (err) { + const error = err as Error; + + if (error && error.status === 404) { + this.isStorageWorking = true; + } } }); @@ -122,7 +134,7 @@ export default class SystemStatusComponent extends Component { getAPIServerStatus = task({ drop: true }, async () => { try { - await this.ajax.request(ENV.endpoints['ping']); + await this.ajax.request(ENV.endpoints['ping'] as string); this.isAPIServerWorking = true; } catch (_) { diff --git a/app/components/user-login/index.ts b/app/components/user-login/index.ts index 5ac996fd8..a5985ef86 100644 --- a/app/components/user-login/index.ts +++ b/app/components/user-login/index.ts @@ -8,17 +8,27 @@ import IntlService from 'ember-intl/services/intl'; import ENV from 'irene/config/environment'; import WhitelabelService from 'irene/services/whitelabel'; -import NetworkService from 'irene/services/network'; import RegistrationService from 'irene/services/registration'; +import type IreneAjaxService from 'irene/services/ajax'; type OtpError = { payload: { type: string; forced: string } }; +type SSOCheckData = { + is_sso: boolean; + is_sso_enforced: boolean; + token: string; +}; + +type SSOSaml2Data = { + url: string; +}; + export default class UserLoginComponent extends Component { @service declare router: RouterService; @service declare intl: IntlService; @service declare session: any; @service declare whitelabel: WhitelabelService; - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service declare notifications: NotificationService; @service declare logger: any; @service declare registration: RegistrationService; @@ -65,27 +75,12 @@ export default class UserLoginComponent extends Component { verifySSOTask = task(async () => { try { - const res = await this.network.post(this.SSOCheckEndpoint, { - username: this.username, + const data = await this.ajax.post(this.SSOCheckEndpoint, { + data: { + username: this.username, + }, }); - if (!res.ok) { - const err = new Error(res.statusText); - - try { - const error_payload = await res.json(); - - // @ts-expect-error TODO: remove/change this later - err.payload = error_payload; - } catch { - err.message = await res.text(); - } - - throw err; - } - - const data = await res.json(); - this.isSSOEnabled = data.is_sso == true; this.isSSOEnforced = data.is_sso_enforced == true; this.checkToken = data.token; @@ -170,8 +165,7 @@ export default class UserLoginComponent extends Component { const endpoint = this.SSOAuthenticateEndpoint; const url = `${endpoint}?token=${token}&return_to=${return_to}`; - const res = await this.network.request(url); - const data = await res.json(); + const data = await this.ajax.request(url); if (!data.url) { this.logger.error('Invalid sso redirect call', data); diff --git a/app/components/user-login/recover-password/index.ts b/app/components/user-login/recover-password/index.ts index 32eea513c..8b0172d07 100644 --- a/app/components/user-login/recover-password/index.ts +++ b/app/components/user-login/recover-password/index.ts @@ -11,6 +11,7 @@ import { BufferedChangeset } from 'ember-changeset/types'; import ENV from 'irene/config/environment'; import LoggerService from 'irene/services/logger'; +import type IreneAjaxService from 'irene/services/ajax'; const ResetValidator = { username: [validatePresence(true)], @@ -21,7 +22,7 @@ type ChangesetBufferProps = BufferedChangeset & { }; export default class UserLoginRecoverPasswordComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service('rollbar') declare logger: LoggerService; @service declare intl: IntlService; @@ -61,7 +62,7 @@ export default class UserLoginRecoverPasswordComponent extends Component { const username = changeset.get('username'); try { - await this.ajax.post(this.recoverURL, { + await this.ajax.post(String(this.recoverURL), { data: { username: username, }, diff --git a/app/components/user-login/reset-password/index.ts b/app/components/user-login/reset-password/index.ts index db8d88e94..d0b7bf41d 100644 --- a/app/components/user-login/reset-password/index.ts +++ b/app/components/user-login/reset-password/index.ts @@ -15,6 +15,7 @@ import { import IntlService from 'ember-intl/services/intl'; import RouterService from '@ember/routing/router-service'; +import type IreneAjaxService from 'irene/services/ajax'; interface UserLoginResetPasswordComponentSignature { Args: { @@ -34,7 +35,7 @@ const ResetValidator = { export default class UserLoginResetPasswordComponent extends Component { @service declare intl: IntlService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare router: RouterService; @service('rollbar') declare logger: any; @service('notifications') declare notify: NotificationService; diff --git a/app/components/user-registration/via-login-page/index.ts b/app/components/user-registration/via-login-page/index.ts index 1f5e92bb0..3fe962566 100644 --- a/app/components/user-registration/via-login-page/index.ts +++ b/app/components/user-registration/via-login-page/index.ts @@ -11,9 +11,9 @@ import { validateFormat, } from 'ember-changeset-validations/validators'; -import NetworkService from 'irene/services/network'; import { ChangesetBufferProps } from '../form'; import IntlService from 'ember-intl/services/intl'; +import type IreneAjaxService from 'irene/services/ajax'; interface RegistrationComponentSignature { Args: { @@ -35,7 +35,7 @@ interface RegistrationData { } export default class RegistrationComponent extends Component { - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service('notifications') declare notify: NotificationService; @service declare intl: IntlService; @@ -88,21 +88,7 @@ export default class RegistrationComponent extends Component { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare router: RouterService; @service('notifications') declare notify: NotificationService; @service declare intl: IntlService; @@ -85,8 +86,7 @@ export default class ViaOrgInviteComponent extends Component { @service declare session: any; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare logger: LoggerService; @service('notifications') declare notify: NotificationService; @service declare intl: IntlService; @@ -62,7 +63,7 @@ export default class ViaPartnerInviteComponent extends Component(url, { + data: { token }, + }); this.notify.success(`Successfully Integrated with user ${data.login}`); } catch (err) { diff --git a/app/routes/authenticated/payment-success.ts b/app/routes/authenticated/payment-success.ts index ad58cfc14..708fa3923 100644 --- a/app/routes/authenticated/payment-success.ts +++ b/app/routes/authenticated/payment-success.ts @@ -2,9 +2,10 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; import config from 'irene/config/environment'; +import type IreneAjaxService from 'irene/services/ajax'; export default class AuthenticatedPaymentSuccessRoute extends Route { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service('browser/window') declare window: Window; @service('notifications') declare notify: NotificationService; diff --git a/app/routes/invite.ts b/app/routes/invite.ts index 1cd6b26d0..0cae99dc8 100644 --- a/app/routes/invite.ts +++ b/app/routes/invite.ts @@ -2,9 +2,10 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; import ENV from 'irene/config/environment'; +import type IreneAjaxService from 'irene/services/ajax'; export default class InviteRoute extends Route { - @service declare ajax: any; + @service declare ajax: IreneAjaxService; async model(params: { token: string }) { const token = params.token; diff --git a/app/services/ajax.js b/app/services/ajax.js deleted file mode 100644 index c0620fb8a..000000000 --- a/app/services/ajax.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable ember/no-computed-properties-in-native-classes, prettier/prettier */ -import { inject as service } from '@ember/service'; -import { computed } from '@ember/object'; -import AjaxService from 'ember-ajax/services/ajax'; -import ENV from 'irene/config/environment'; - - -// https://github.com/ember-cli/ember-ajax/blob/c178c5e28a316a23cd1da5736c0e29621d838cb1/addon/-private/utils/url-helpers.ts#L55 -const completeUrlRegex = /^(http|https)/; - -function isFullURL(url) { - return !!url.match(completeUrlRegex); -} - -export default class IreneAjaxService extends AjaxService { - host = ENV.host; - namespace = ENV.namespace; - @service session; - _buildURL(url, options) { - const ret = super._buildURL(url, options); - if(isFullURL(ret)) { - return ret; - } - if(ret.length && ret[0] !== '/') { - return '/' + ret; - } - return ret; - } - @computed('session.data.authenticated.b64token', function () { - const token = this.session.data.authenticated.b64token; - if(token) { - return { - 'Authorization': "Basic " + token, - 'X-Product': ENV.product - }; - } - return { - 'X-Product': ENV.product - }; - }) - headers; -} diff --git a/app/services/ajax.ts b/app/services/ajax.ts new file mode 100644 index 000000000..76b0547ca --- /dev/null +++ b/app/services/ajax.ts @@ -0,0 +1,314 @@ +import Service, { inject as service } from '@ember/service'; +import { tracked } from '@glimmer/tracking'; + +import fetch from 'fetch'; +import ENV from 'irene/config/environment'; + +/** + * Extended request options that include additional properties beyond the standard RequestInit + */ +interface RequestOptions extends RequestInit { + /** Optional data to be sent as JSON in the request body */ + data?: unknown; + /** Additional headers to merge with default headers */ + headers?: Record; + /** Optional namespace to override the default API namespace */ + namespace?: string; + /** Optional host URL to override the default API host */ + host?: string; +} + +/** + * Structure for default headers sent with every request + */ +interface DefaultHeaders { + /** Basic authentication token */ + Authorization?: string; + /** Product identifier header */ + 'X-Product': string; +} + +const completeUrlRegex = /^(http|https)/; + +function isFullURL(url: string): boolean { + return !!url.match(completeUrlRegex); +} + +function startsWithSlash(string: string) { + return string.charAt(0) === '/'; +} + +function endsWithSlash(string: string) { + return string.charAt(string.length - 1) === '/'; +} + +function removeLeadingSlash(string: string) { + return string.substring(1); +} + +function removeTrailingSlash(string: string) { + return string.slice(0, -1); +} + +function stripSlashes(path: string) { + // make sure path starts with `/` + if (startsWithSlash(path)) { + path = removeLeadingSlash(path); + } + + // remove end `/` + if (endsWithSlash(path)) { + path = removeTrailingSlash(path); + } + return path; +} + +function haveSameHost(a: string, b: string): boolean { + const urlA = parseURL(a); + const urlB = parseURL(b); + + return ( + urlA.protocol === urlB.protocol && + urlA.hostname === urlB.hostname && + urlA.port === urlB.port + ); +} + +export function parseURL(str: string) { + let fullObject; + + // @ts-expect-error no types + if (typeof FastBoot === 'undefined') { + const element = document.createElement('a'); + element.href = str; + fullObject = element; + } else { + // @ts-expect-error no types + fullObject = FastBoot.require('url').parse(str); + } + + return { + href: fullObject.href, + protocol: fullObject.protocol, + hostname: fullObject.hostname, + port: fullObject.port, + pathname: fullObject.pathname, + search: fullObject.search, + hash: fullObject.hash, + }; +} + +export default class IreneAjaxService extends Service { + @service declare session: any; + @tracked headers?: Record; + + host: string = ENV.environment === 'test' ? window.location.origin : ENV.host; + + namespace: string = ENV.namespace; + trustedHosts: string[] = []; + + /** + * Returns the default headers for all requests + * Includes authentication token if available and product identifier + */ + get defaultHeaders(): DefaultHeaders { + const token = this.session.data.authenticated.b64token; + + if (token) { + return { + Authorization: 'Basic ' + token, + 'X-Product': String(ENV.product), + }; + } + + return { + 'X-Product': String(ENV.product), + }; + } + + /** + * Constructs the complete URL for the API request + * @param url - The endpoint URL + * @param options - Optional request options to override the default + * @returns The complete URL with host and namespace + */ + private _buildURL(url: string, options: RequestOptions = {}): string { + if (isFullURL(url)) { + return url; + } + + const urlParts = []; + + let host = options.host || this.host; + + if (host) { + host = endsWithSlash(host) ? removeTrailingSlash(host) : host; + urlParts.push(host); + } + + let namespace = options.namespace || this.namespace; + + if (namespace) { + // If host is given then we need to strip leading slash too( as it will be added through join) + if (host) { + namespace = stripSlashes(namespace); + } else if (endsWithSlash(namespace)) { + namespace = removeTrailingSlash(namespace); + } + + // If the URL has already been constructed (presumably, by Ember Data), then we should just leave it alone + const hasNamespaceRegex = new RegExp(`^(/)?${stripSlashes(namespace)}/`); + + if (!hasNamespaceRegex.test(url)) { + urlParts.push(namespace); + } + } + + // *Only* remove a leading slash when there is host or namespace -- we need to maintain a trailing slash for + // APIs that differentiate between it being and not being present + if (startsWithSlash(url) && urlParts.length !== 0) { + url = removeLeadingSlash(url); + } + + urlParts.push(url); + + return urlParts.join('/'); + } + + /** + * Determines whether headers should be sent for a given request + * @param url - The request URL + * @param host - Optional host override + * @returns boolean indicating whether headers should be sent + */ + private _shouldSendHeaders(url: string, host?: string): boolean { + host = host || this.host; + const { hostname } = parseURL(url); + + // Add headers on relative URLs + if (!isFullURL(url)) { + return true; + } else if ( + this.trustedHosts.find((matcher) => this._matchHosts(hostname, matcher)) + ) { + return true; + } + + // Add headers on matching host + return haveSameHost(url, host); + } + + /** + * Matches a hostname against a pattern + * @param hostname - The hostname to check + * @param pattern - The pattern to match against + * @returns boolean indicating whether the hostname matches + */ + private _matchHosts(hostname: string, pattern: string): boolean { + // Convert pattern to regex-compatible string + const regexPattern = pattern.replace(/\./g, '\\.').replace(/\*/g, '.*'); + return new RegExp(`^${regexPattern}$`).test(hostname); + } + + /** + * Makes an HTTP request to the specified endpoint + * @param url - The endpoint URL + * @param options - Request options including method, headers, data, etc. + * @returns Promise resolving to the JSON response + * @throws Response object if the request fails + */ + async makeRequest(url: string, options: RequestOptions = {}): Promise { + const finalUrl = this._buildURL(url, options); + + // Only include headers if _shouldSendHeaders returns true + const headers = this._shouldSendHeaders(finalUrl, options.host) + ? { + 'Content-Type': 'application/json', + ...this.defaultHeaders, + ...options.headers, + } + : options.headers || {}; + + const fetchOptions: RequestInit = { + ...options, + headers, + body: options.data ? JSON.stringify(options.data) : undefined, + }; + + delete (fetchOptions as RequestOptions).namespace; + + const response = await fetch(finalUrl, fetchOptions); + + if (!response.ok) { + const parsedResponse = await this.parseResponseText(response); + + const errorResponse = { + ...response, + ...(typeof parsedResponse === 'object' + ? parsedResponse + : { message: parsedResponse }), + payload: parsedResponse, + }; + + throw errorResponse; + } + + return (await this.parseResponseText(response)) as T; + } + + /** + * Parses the response text as JSON if possible, otherwise returns raw text. + * + * @param {Response} response - The fetch response to parse. + * @returns {Promise} - The parsed JSON or raw text. + */ + private async parseResponseText(response: Response): Promise { + const text = await response.text(); + + try { + return text ? JSON.parse(text) : {}; + } catch { + return text; + } + } + + /** + * Makes a POST request to the specified endpoint + * @param url - The endpoint URL + * @param options - Request options including headers, data, etc. + * @returns Promise resolving to the JSON response + */ + post(url: string, options: RequestOptions = {}): Promise { + return this.makeRequest(url, { ...options, method: 'POST' }); + } + + /** + * Makes a PUT request to the specified endpoint + * @param url - The endpoint URL + * @param options - Request options including headers, data, etc. + * @returns Promise resolving to the JSON response + */ + put(url: string, options: RequestOptions = {}): Promise { + return this.makeRequest(url, { ...options, method: 'PUT' }); + } + + /** + * Makes a GET request to the specified endpoint + * @param url - The endpoint URL + * @param options - Request options including headers, namespace, etc. + * @returns Promise resolving to the JSON response + */ + request(url: string, options: RequestOptions = {}): Promise { + return this.makeRequest(url, { ...options, method: 'GET' }); + } + + /** + * Makes a DELETE request to the specified endpoint + * @param url - The endpoint URL + * @param options - Request options including headers, etc. + * @returns Promise resolving to the JSON response + */ + delete(url: string, options: RequestOptions = {}): Promise { + return this.makeRequest(url, { ...options, method: 'DELETE' }); + } +} diff --git a/app/services/configuration.ts b/app/services/configuration.ts index 2741f3ccb..b1b09d66a 100644 --- a/app/services/configuration.ts +++ b/app/services/configuration.ts @@ -2,8 +2,8 @@ import { inject as service } from '@ember/service'; import Service from '@ember/service'; import Store from '@ember-data/store'; -import NetworkService from './network'; import LoggerService from './logger'; +import IreneAjaxService from './ajax'; type ServerData = { websocket: string; @@ -17,8 +17,59 @@ type DashboardData = { devicefarmURL: string; }; +type ImageData = { + logo_on_darkbg: string; + logo_on_lightbg: string; + favicon: string; +}; + +type IntegrationData = { + freshchat_key: string; + hotjar_key: string; + pendo_key: string; + csb_key: string; + rollbar_key: string; + freshdesk_configuration: { + widget_id: string; + }; +}; + +type ThemeData = { + scheme: string; + primary_color: string; + primary_alt_color: string; + secondary_color: string; + secondary_alt_color: string; +}; + +type FrontendConfigResponse = { + name: string; + hide_poweredby_logo: boolean; + url: string; + registration_enabled: boolean; + registration_link: string; + + images: ImageData; + + integrations: IntegrationData; + + theme: ThemeData; +}; + +type ServerResponse = { + websocket: string; + devicefarm_url: string; + enterprise: string | boolean; + url_upload_allowed: boolean; +}; + +type DashboardResponse = { + dashboard_url: string; + devicefarm_url: string; +}; + export default class ConfigurationService extends Service { - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service declare logger: LoggerService; @service declare store: Store; @service declare session: any; @@ -39,7 +90,7 @@ export default class ConfigurationService extends Service { registration_link: '', }; - themeData = { + themeData: ThemeData = { scheme: '', primary_color: '', primary_alt_color: '', @@ -47,13 +98,13 @@ export default class ConfigurationService extends Service { secondary_alt_color: '', }; - imageData = { + imageData: ImageData = { favicon: '', logo_on_darkbg: '', logo_on_lightbg: '', }; - integrationData = { + integrationData: IntegrationData = { freshchat_key: '', freshdesk_configuration: { widget_id: '', @@ -76,19 +127,12 @@ export default class ConfigurationService extends Service { devicefarmURL: '', }; - async fetchConfig(url: string) { - const res = await this.network.request(url); - - if (res.ok) { - return await res.json(); - } - - throw new Error(`Error fetching ${url} configuration`); - } - async frontendConfigFetch() { try { - const data = await this.fetchConfig(this.frontendConfigEndpoint); + const data = await this.ajax.request( + this.frontendConfigEndpoint + ); + this.frontendData.hide_poweredby_logo = data.hide_poweredby_logo == true; this.frontendData.name ||= data.name; this.frontendData.registration_enabled ||= @@ -157,7 +201,9 @@ export default class ConfigurationService extends Service { async serverConfigFetch() { try { - const data = await this.fetchConfig(this.serverConfigEndpoint); + const data = await this.ajax.request( + this.serverConfigEndpoint + ); this.serverData.websocket ||= data.websocket; this.serverData.enterprise ||= data.enterprise == true; @@ -179,7 +225,9 @@ export default class ConfigurationService extends Service { async dashboardConfigFetch() { try { - const data = await this.fetchConfig(this.dashboardConfigEndpoint); + const data = await this.ajax.request( + this.dashboardConfigEndpoint + ); this.dashboardData.dashboardURL ||= data.dashboard_url; this.dashboardData.devicefarmURL ||= data.devicefarm_url; diff --git a/app/services/devicefarm.ts b/app/services/devicefarm.ts index 4a9db932c..9eac46384 100644 --- a/app/services/devicefarm.ts +++ b/app/services/devicefarm.ts @@ -1,11 +1,17 @@ import Service from '@ember/service'; import { inject as service } from '@ember/service'; + import ENV from 'irene/config/environment'; import ConfigurationService from './configuration'; +import type IreneAjaxService from './ajax'; + +type DevicefarmPingResponse = { + ping: string; +}; export default class DevicefarmService extends Service { @service declare session: any; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @service declare configuration: ConfigurationService; pingEndpoint = '/devicefarm/ping'; @@ -24,7 +30,8 @@ export default class DevicefarmService extends Service { async testPing() { const pingUrl = new URL(this.pingEndpoint, this.urlbase).href; - const pingContent = await this.ajax.request(pingUrl); + const pingContent = + await this.ajax.request(pingUrl); return pingContent['ping'] === 'pong'; } diff --git a/app/services/freshdesk.ts b/app/services/freshdesk.ts index 538d959d3..2d34c602a 100644 --- a/app/services/freshdesk.ts +++ b/app/services/freshdesk.ts @@ -6,15 +6,21 @@ import { action } from '@ember/object'; import type ConfigurationService from './configuration'; import type LoggerService from './logger'; -import type NetworkService from './network'; import type OrganizationService from './organization'; import type UserModel from 'irene/models/user'; +import type IreneAjaxService from './ajax'; + +type WidgetAuthResponse = { + token: string; + name: string; + email: string; +}; export default class FreshdeskService extends Service { @service('browser/window') declare window: Window; @service declare configuration: ConfigurationService; @service declare logger: LoggerService; - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service declare organization: OrganizationService; @tracked widgetAuthToken = ''; @@ -100,8 +106,9 @@ export default class FreshdeskService extends Service { @action async authWidgetCallback() { try { - const authRes = await this.network.post(this.WIDGET_AUTH_ENDPOINT); - const widgetAuthData = await authRes.json(); + const widgetAuthData = await this.ajax.post( + this.WIDGET_AUTH_ENDPOINT + ); this.window.FreshworksWidget('authenticate', { token: widgetAuthData.token, @@ -140,8 +147,10 @@ export default class FreshdeskService extends Service { getFreshWidgetToken = task(async () => { try { - const authRes = await this.network.post(this.WIDGET_AUTH_ENDPOINT); - const widgetAuthData = await authRes.json(); + const widgetAuthData = await this.ajax.post( + this.WIDGET_AUTH_ENDPOINT + ); + this.widgetAuthToken = widgetAuthData.token; } catch (error) { this.logger.error(error); diff --git a/app/services/oidc.ts b/app/services/oidc.ts index 546c6a899..6cf0ef568 100644 --- a/app/services/oidc.ts +++ b/app/services/oidc.ts @@ -3,7 +3,7 @@ import RouterService from '@ember/routing/router-service'; import { task } from 'ember-concurrency'; import IntlService from 'ember-intl/services/intl'; -import NetworkService from 'irene/services/network'; +import type IreneAjaxService from 'irene/services/ajax'; interface OidcResponse { valid: boolean; @@ -32,7 +32,7 @@ export interface OidcAuthorizationResponse { } export default class OidcService extends Service { - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service declare session: any; @service declare intl: IntlService; @service declare router: RouterService; @@ -61,27 +61,31 @@ export default class OidcService extends Service { } authorizeOidcAppPermissions = task(async (token: string, allow?: boolean) => { - const res = await this.network.post(this.oidcAuthorizeEndpoint, { - oidc_token: token, - allow, - }); - - const data = (await res.json()) as OidcAuthorizeResult; - - if (data.error) { - if (data.redirect_url) { + try { + const data = await this.ajax.post( + this.oidcAuthorizeEndpoint, + { + data: { oidc_token: token, allow }, + } + ); + + if (data.valid && data.redirect_url) { this.window.location.href = data.redirect_url; - } else { - this.notify.error( - data.error.description || this.intl.t('somethingWentWrong') - ); } + } catch (e) { + const err = e as OidcAuthorizeResult; + + if (err.error) { + if (err.redirect_url) { + this.window.location.href = err.redirect_url; + } else { + this.notify.error( + err.error.description || this.intl.t('somethingWentWrong') + ); + } - return; - } - - if (data.valid && data.redirect_url) { - this.window.location.href = data.redirect_url; + return; + } } }); @@ -90,39 +94,39 @@ export default class OidcService extends Service { await this.validateOidcToken.perform(token); } else { this.router.transitionTo('login'); - this.window.sessionStorage.setItem('oidc_token', token); } } validateOidcToken = task(async (token: string) => { - const res = await this.network.post(this.oidcTokenValidateEndpoint, { - oidc_token: token, - }); - - const data = (await res.json()) as ValidateOidcTokenResponse; - - if (res.status === 400 || data.error) { - if (data.redirect_url) { - this.window.location.href = data.redirect_url; - - return; - } else { - throw { - name: 'Error', - statusCode: res.status, - code: data.error?.code, - description: data.error?.description, - }; + try { + const data = await this.ajax.post( + this.oidcTokenValidateEndpoint, + { + data: { oidc_token: token }, + } + ); + + if (data.valid) { + this.router.transitionTo('oidc.authorize', { + queryParams: { oidc_token: token }, + }); + } + } catch (e) { + const err = e as ValidateOidcTokenResponse; + + if (err.error) { + if (err.redirect_url) { + this.window.location.href = err.redirect_url; + return; + } else { + throw { + name: 'Error', + code: err.error?.code, + description: err.error?.description, + }; + } } - } - - if (data.valid) { - this.router.transitionTo('oidc.authorize', { - queryParams: { - oidc_token: token, - }, - }); } }); @@ -134,33 +138,35 @@ export default class OidcService extends Service { }; } else { this.router.transitionTo('login'); - this.window.sessionStorage.setItem('oidc_token', token); } } fetchOidcAuthorizationData = task(async (token: string) => { - const res = await this.network.post(this.oidcAuthorizationEndpoint, { - oidc_token: token, - }); - - const data = (await res.json()) as OidcAuthorizationResponse; - - if (res.status === 400 || data.validation_result.error) { - if (data.validation_result.redirect_url) { - this.window.location.href = data.validation_result.redirect_url; - - return; - } else { - throw { - name: 'Error', - statusCode: res.status, - code: data.validation_result.error?.code, - description: data.validation_result.error?.description, - }; + try { + const data = await this.ajax.post( + this.oidcAuthorizationEndpoint, + { + data: { oidc_token: token }, + } + ); + + return data; + } catch (error) { + const err = error as OidcAuthorizationResponse; + + if (err.validation_result.error) { + if (err.validation_result.redirect_url) { + this.window.location.href = err.validation_result.redirect_url; + return; + } else { + throw { + name: 'Error', + code: err.validation_result.error?.code, + description: err.validation_result.error?.description, + }; + } } } - - return data; }); } diff --git a/app/services/organization.ts b/app/services/organization.ts index 3d1982074..a34d79242 100644 --- a/app/services/organization.ts +++ b/app/services/organization.ts @@ -4,11 +4,12 @@ import ENV from 'irene/config/environment'; import Store from '@ember-data/store'; import OrganizationModel from '../models/organization'; import { tracked } from '@glimmer/tracking'; +import type IreneAjaxService from './ajax'; export default class OrganizationService extends Service { @service declare store: Store; @service declare notifications: NotificationService; - @service declare ajax: any; + @service declare ajax: IreneAjaxService; @tracked selected: OrganizationModel | null = null; @tracked isSecurityEnabled = false; diff --git a/app/services/websocket.ts b/app/services/websocket.ts index 7ac7e1272..ff7379e6e 100644 --- a/app/services/websocket.ts +++ b/app/services/websocket.ts @@ -10,8 +10,8 @@ import ENV from 'irene/config/environment'; import type ConfigurationService from './configuration'; import type RealtimeService from './realtime'; import type AkNotificationsService from './ak-notifications'; -import type NetworkService from './network'; import type UserModel from 'irene/models/user'; +import type IreneAjaxService from './ajax'; export interface SocketInstance { on: (event: string, handler: (args: any) => void, target?: object) => void; @@ -34,7 +34,7 @@ export default class WebsocketService extends Service { @service declare realtime: RealtimeService; @service declare notifications: NotificationService; @service declare akNotifications: AkNotificationsService; - @service declare network: NetworkService; + @service declare ajax: IreneAjaxService; @service('socket-io') socketIOService: any; connectionPath = '/websocket'; @@ -51,8 +51,8 @@ export default class WebsocketService extends Service { return hostFromConfig; } - if (this.network.host) { - return this.network.host; + if (this.ajax.host) { + return this.ajax.host; } return '/'; diff --git a/package-lock.json b/package-lock.json index aba0311ff..2db4c4a19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -87,7 +87,6 @@ "cross-env": "^7.0.3", "cypress-visual-regression": "5.0.0", "dayjs": "^1.11.9", - "ember-ajax": "^5.1.2", "ember-auto-import": "^2.7.2", "ember-basic-dropdown": "^8.3.0", "ember-browser-services": "^4.0.4", @@ -22258,289 +22257,6 @@ "dev": true, "license": "MIT" }, - "node_modules/ember-ajax": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ember-cli-babel": "^7.5.0", - "najax": "^1.0.7" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/ember-ajax/node_modules/@babel/runtime": { - "version": "7.12.18", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.13.4" - } - }, - "node_modules/ember-ajax/node_modules/@types/fs-extra": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ember-ajax/node_modules/babel-plugin-module-resolver": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-babel-config": "^1.1.0", - "glob": "^7.1.2", - "pkg-up": "^2.0.0", - "reselect": "^3.0.1", - "resolve": "^1.4.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ember-ajax/node_modules/broccoli-source": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/ember-ajax/node_modules/ember-cli-babel": { - "version": "7.26.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.12.0", - "@babel/helper-compilation-targets": "^7.12.0", - "@babel/plugin-proposal-class-properties": "^7.16.5", - "@babel/plugin-proposal-decorators": "^7.13.5", - "@babel/plugin-proposal-private-methods": "^7.16.5", - "@babel/plugin-proposal-private-property-in-object": "^7.16.5", - "@babel/plugin-transform-modules-amd": "^7.13.0", - "@babel/plugin-transform-runtime": "^7.13.9", - "@babel/plugin-transform-typescript": "^7.13.0", - "@babel/polyfill": "^7.11.5", - "@babel/preset-env": "^7.16.5", - "@babel/runtime": "7.12.18", - "amd-name-resolver": "^1.3.1", - "babel-plugin-debug-macros": "^0.3.4", - "babel-plugin-ember-data-packages-polyfill": "^0.1.2", - "babel-plugin-ember-modules-api-polyfill": "^3.5.0", - "babel-plugin-module-resolver": "^3.2.0", - "broccoli-babel-transpiler": "^7.8.0", - "broccoli-debug": "^0.6.4", - "broccoli-funnel": "^2.0.2", - "broccoli-source": "^2.1.2", - "calculate-cache-key-for-tree": "^2.0.0", - "clone": "^2.1.2", - "ember-cli-babel-plugin-helpers": "^1.1.1", - "ember-cli-version-checker": "^4.1.0", - "ensure-posix-path": "^1.0.2", - "fixturify-project": "^1.10.0", - "resolve-package-path": "^3.1.0", - "rimraf": "^3.0.1", - "semver": "^5.5.0" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/ember-ajax/node_modules/ember-cli-babel/node_modules/semver": { - "version": "5.7.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ember-ajax/node_modules/ember-cli-version-checker": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-package-path": "^2.0.0", - "semver": "^6.3.0", - "silent-error": "^1.1.1" - }, - "engines": { - "node": "8.* || 10.* || >= 12.*" - } - }, - "node_modules/ember-ajax/node_modules/ember-cli-version-checker/node_modules/resolve-package-path": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-root": "^0.1.1", - "resolve": "^1.13.1" - }, - "engines": { - "node": "8.* || 10.* || >= 12" - } - }, - "node_modules/ember-ajax/node_modules/find-up": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ember-ajax/node_modules/fixturify": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/fs-extra": "^5.0.5", - "@types/minimatch": "^3.0.3", - "@types/rimraf": "^2.0.2", - "fs-extra": "^7.0.1", - "matcher-collection": "^2.0.0" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/ember-ajax/node_modules/fixturify-project": { - "version": "1.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fixturify": "^1.2.0", - "tmp": "^0.0.33" - } - }, - "node_modules/ember-ajax/node_modules/fs-extra": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/ember-ajax/node_modules/jsonfile": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/ember-ajax/node_modules/locate-path": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ember-ajax/node_modules/p-limit": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ember-ajax/node_modules/p-locate": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ember-ajax/node_modules/p-try": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ember-ajax/node_modules/pkg-up": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ember-ajax/node_modules/reselect": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/ember-ajax/node_modules/resolve-package-path": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-root": "^0.1.1", - "resolve": "^1.17.0" - }, - "engines": { - "node": "10.* || >= 12" - } - }, - "node_modules/ember-ajax/node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ember-ajax/node_modules/tmp": { - "version": "0.0.33", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/ember-ajax/node_modules/universalify": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/ember-assign-helper": { "version": "0.5.0", "dev": true, @@ -47266,14 +46982,6 @@ "dev": true, "license": "MIT" }, - "node_modules/jquery-deferred": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/js-file-download": { "version": "0.4.12", "license": "MIT" @@ -48729,19 +48437,6 @@ "dev": true, "license": "ISC" }, - "node_modules/najax": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "jquery-deferred": "^0.3.0", - "lodash": "^4.17.21", - "qs": "^6.2.0" - }, - "engines": { - "node": ">= 4.4.3" - } - }, "node_modules/nan": { "version": "2.20.0", "dev": true, @@ -61632,6 +61327,7 @@ "node_modules/netlify-cli/node_modules/unix-dgram": { "version": "2.0.6", "dev": true, + "hasInstallScript": true, "license": "ISC", "optional": true, "dependencies": { diff --git a/package.json b/package.json index 3c325ea39..433217085 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,6 @@ "cross-env": "^7.0.3", "cypress-visual-regression": "5.0.0", "dayjs": "^1.11.9", - "ember-ajax": "^5.1.2", "ember-auto-import": "^2.7.2", "ember-basic-dropdown": "^8.3.0", "ember-browser-services": "^4.0.4", diff --git a/tests/acceptance/file-details/manual-scan-test.js b/tests/acceptance/file-details/manual-scan-test.js index c0d0baee9..c5d6c56c6 100644 --- a/tests/acceptance/file-details/manual-scan-test.js +++ b/tests/acceptance/file-details/manual-scan-test.js @@ -250,7 +250,9 @@ module('Acceptance | file-details/manual-scan', function (hooks) { }); this.server.put('manualscans/:id', (_, req) => { - const data = JSON.parse(req.requestBody); + const reqBody = JSON.parse(req.requestBody); + + const data = JSON.parse(reqBody); assert.strictEqual(data.app_env, this.appEnv); assert.strictEqual(data.min_os_version, `${this.minOsVersion}`); diff --git a/tests/integration/components/file-details/dynamic-scan/manual-test.js b/tests/integration/components/file-details/dynamic-scan/manual-test.js index c572413b9..a92172a65 100644 --- a/tests/integration/components/file-details/dynamic-scan/manual-test.js +++ b/tests/integration/components/file-details/dynamic-scan/manual-test.js @@ -106,10 +106,7 @@ module( }); this.server.put('/profiles/:id/device_preference', (_, req) => { - const data = req.requestBody - .split('&') - .map((it) => it.split('=')) - .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); + const data = JSON.parse(req.requestBody); this.set('requestBody', data); @@ -1013,7 +1010,7 @@ module( // verify network data assert.strictEqual( this.requestBody.device_type, - `${ENUMS.DEVICE_TYPE.PHONE_REQUIRED}` + ENUMS.DEVICE_TYPE.PHONE_REQUIRED ); const filteredDevices = this.availableDevices.filter( @@ -1599,10 +1596,7 @@ module( ); this.server.put('/profiles/:id/device_preference', (schema, req) => { - const data = req.requestBody - .split('&') - .map((it) => it.split('=')) - .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); + const data = JSON.parse(req.requestBody); this.set('requestBody', data); @@ -1616,7 +1610,7 @@ module( assert.strictEqual( data.device_type, - String(actualDevicePrefData.device_type) + actualDevicePrefData.device_type ); assert.strictEqual( @@ -1630,7 +1624,7 @@ module( assert.strictEqual( data.device_type, - String(ENUMS.DEVICE_TYPE.PHONE_REQUIRED) + ENUMS.DEVICE_TYPE.PHONE_REQUIRED ); this.set('checkPreferenceReset', true); diff --git a/tests/integration/components/file-details/summary-test.js b/tests/integration/components/file-details/summary-test.js index 4f5724eac..938e51822 100644 --- a/tests/integration/components/file-details/summary-test.js +++ b/tests/integration/components/file-details/summary-test.js @@ -210,7 +210,9 @@ module('Integration | Component | file-details/summary', function (hooks) { return new Response(500, {}, { errors: ['server error'] }); } - const tag = schema.create('tag', { name: req.requestBody.split('=')[1] }); + const requestBody = JSON.parse(req.requestBody); + + const tag = schema.create('tag', { name: requestBody.name }); const file = schema.files.find(this.file.id); file.tags.push(tag.toJSON()); diff --git a/tests/integration/components/file-details/vulnerability-analysis-details/edit-analysis-button-test.js b/tests/integration/components/file-details/vulnerability-analysis-details/edit-analysis-button-test.js index e7c5c0a31..a4898db6f 100644 --- a/tests/integration/components/file-details/vulnerability-analysis-details/edit-analysis-button-test.js +++ b/tests/integration/components/file-details/vulnerability-analysis-details/edit-analysis-button-test.js @@ -398,17 +398,15 @@ module( this.server.put( '/files/:fileId/vulnerability_preferences/:id/risk', (schema, req) => { - const data = req.requestBody - .split('&') - .map((it) => it.split('=')) - .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); + const data = JSON.parse(req.requestBody); - assert.strictEqual(data.risk, `${overrideToRisk}`); + assert.strictEqual(data.risk, overrideToRisk); assert.strictEqual(data.comment, 'testing'); assert.strictEqual( data.all, - `${overrideForOptions[0].value === ENUMS.ANALYSIS_OVERRIDE_CRITERIA.ALL_FUTURE_UPLOAD}` + overrideForOptions[0].value === + ENUMS.ANALYSIS_OVERRIDE_CRITERIA.ALL_FUTURE_UPLOAD ); schema.analyses.find(analysisId).update({ @@ -596,7 +594,7 @@ module( this.server.delete( '/files/:fileId/vulnerability_preferences/:id/risk', (schema, req) => { - assert.strictEqual(req.requestBody, `all=${resetAll}`); + assert.strictEqual(req.requestBody, `{"all":${resetAll}}`); schema.analyses.find(analysisId).update({ overridden_risk: null, diff --git a/tests/integration/components/file/report-drawer/va-reports/report-item-test.js b/tests/integration/components/file/report-drawer/va-reports/report-item-test.js index 2d78c0e96..7e6a94727 100644 --- a/tests/integration/components/file/report-drawer/va-reports/report-item-test.js +++ b/tests/integration/components/file/report-drawer/va-reports/report-item-test.js @@ -1,7 +1,7 @@ import { faker } from '@faker-js/faker'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { click, render } from '@ember/test-helpers'; +import { click, render, waitUntil } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupIntl, t } from 'ember-intl/test-support'; import { setupMirage } from 'ember-cli-mirage/test-support'; @@ -230,6 +230,8 @@ module( const window = this.owner.lookup('service:browser/window'); + await waitUntil(() => window.url); + assert.strictEqual( window.url, `${type}_download_url.com`, @@ -271,6 +273,8 @@ module( const notifyService = this.owner.lookup('service:notifications'); + await waitUntil(() => notifyService.get('errorMsg')); + assert.strictEqual(notifyService.errorMsg, t('downloadUrlNotFound')); }); } diff --git a/tests/integration/components/partner/client-report-download-test.js b/tests/integration/components/partner/client-report-download-test.js index 3687766bc..f455ce553 100644 --- a/tests/integration/components/partner/client-report-download-test.js +++ b/tests/integration/components/partner/client-report-download-test.js @@ -3,7 +3,13 @@ import dayjs from 'dayjs'; import { Response } from 'miragejs'; import { setupRenderingTest } from 'ember-qunit'; import Service from '@ember/service'; -import { render, click, find, triggerEvent } from '@ember/test-helpers'; +import { + render, + click, + find, + triggerEvent, + waitUntil, +} from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupIntl, t } from 'ember-intl/test-support'; import { setupMirage } from 'ember-cli-mirage/test-support'; @@ -698,8 +704,12 @@ module( assert .dom(`[data-test-report-password-toggle-id="${report.id}"]`) .exists(); + + await waitUntil(() => find('[data-test-report-password-title]')); + assert.dom('[data-test-dropdown-tray]').exists(); assert.dom('[data-test-report-password]').exists(); + assert .dom('[data-test-report-password-title]') .hasText(t('reportPassword')); @@ -757,6 +767,8 @@ module( await click(downloadBtn); + await waitUntil(() => notifyService.get('errorMsg')); + assert.strictEqual( notifyService.get('errorMsg'), t('downloadUrlNotFound') diff --git a/tests/integration/components/project-settings/analysis-settings/vulnerability-list/index-test.js b/tests/integration/components/project-settings/analysis-settings/vulnerability-list/index-test.js index d4443ddf1..4336adfe6 100644 --- a/tests/integration/components/project-settings/analysis-settings/vulnerability-list/index-test.js +++ b/tests/integration/components/project-settings/analysis-settings/vulnerability-list/index-test.js @@ -12,7 +12,6 @@ import ENUMS from 'irene/enums'; import akSelectStyles from 'irene/components/ak-select/index.scss'; import { analysisRiskStatus } from 'irene/helpers/analysis-risk-status'; import { riskText } from 'irene/helpers/risk-text'; -import { getReqBodyObjFromReqBodyStr } from 'irene/tests/helpers/mirage-utils'; // General Selectors for common elements const GENERAL_SELECTORS = { @@ -417,7 +416,7 @@ module( this.server.put( '/profiles/1/vulnerability_preferences/:id', (schema, req) => { - const { comment, risk } = getReqBodyObjFromReqBodyStr(req); + const { comment, risk } = JSON.parse(req.requestBody); // Selected overriden risk assert.strictEqual(Number(risk), riskToEditTo); @@ -643,7 +642,7 @@ module( this.server.put( '/profiles/1/vulnerability_preferences/:id', (schema, req) => { - const { comment, risk } = getReqBodyObjFromReqBodyStr(req); + const { comment, risk } = JSON.parse(req.requestBody); // Selected overriden risk assert.strictEqual(Number(risk), riskToEditTo); @@ -868,7 +867,7 @@ module( this.server.put( '/profiles/1/vulnerability_preferences/:id', (schema, req) => { - const { comment, risk } = getReqBodyObjFromReqBodyStr(req); + const { comment, risk } = JSON.parse(req.requestBody); // Selected overriden risk assert.true(isEmpty(risk)); diff --git a/tests/integration/components/project-settings/general-settings/dynamicscan-automation-settings/index-test.js b/tests/integration/components/project-settings/general-settings/dynamicscan-automation-settings/index-test.js index 2a84282f6..4e6122e66 100644 --- a/tests/integration/components/project-settings/general-settings/dynamicscan-automation-settings/index-test.js +++ b/tests/integration/components/project-settings/general-settings/dynamicscan-automation-settings/index-test.js @@ -5,7 +5,6 @@ import { hbs } from 'ember-cli-htmlbars'; import { setupMirage } from 'ember-cli-mirage/test-support'; import { setupIntl, t } from 'ember-intl/test-support'; import Service from '@ember/service'; -import { objectifyEncodedReqBody } from 'irene/tests/test-utils'; class NotificationsStub extends Service { errorMsg = null; @@ -102,7 +101,7 @@ module( test('it toggles scheduled automation', async function (assert) { this.server.put('/profiles/:id/dynamicscan_mode', (schema, req) => { - const reqBody = objectifyEncodedReqBody(req.requestBody); + const reqBody = JSON.parse(req.requestBody); this.set('dynamicscan_mode', reqBody.dynamicscan_mode); diff --git a/tests/integration/components/security/analysis-details-test.js b/tests/integration/components/security/analysis-details-test.js index 875b0e829..1f0041d83 100644 --- a/tests/integration/components/security/analysis-details-test.js +++ b/tests/integration/components/security/analysis-details-test.js @@ -20,7 +20,6 @@ import { riskText } from 'irene/helpers/risk-text'; import ENUMS from 'irene/enums'; import styles from 'irene/components/ak-select/index.scss'; -import { objectifyEncodedReqBody } from 'irene/tests/test-utils'; // JSON API Serializer const serializeForJsonApi = (payload, type) => ({ @@ -563,7 +562,9 @@ module('Integration | Component | security/analysis-details', function (hooks) { risk: ENUMS.RISK.UNKNOWN, }; - const data = JSON.parse(req.requestBody); + const reqBody = JSON.parse(req.requestBody); + + const data = JSON.parse(reqBody); // Sanity check for values sent to API Object.keys(untestedCvssState).forEach((key) => @@ -830,7 +831,7 @@ module('Integration | Component | security/analysis-details', function (hooks) { this.server.post( '/hudson-api/attachments/upload_finished', (schema, req) => { - const reqBody = objectifyEncodedReqBody(req.requestBody); + const reqBody = JSON.parse(req.requestBody); // Create an attachment const attachment = this.server.create('security/attachment', { diff --git a/tests/integration/components/user-login/recover-password-test.js b/tests/integration/components/user-login/recover-password-test.js index 719adb95a..e48942819 100644 --- a/tests/integration/components/user-login/recover-password-test.js +++ b/tests/integration/components/user-login/recover-password-test.js @@ -59,7 +59,9 @@ module( const username = 'appknox'; this.server.post('/v2/forgot_password', (schema, req) => { - const reqUsername = req.requestBody.split('=')[1]; + const reqBody = JSON.parse(req.requestBody); + + const reqUsername = reqBody.username; assert.strictEqual(username, reqUsername); @@ -101,7 +103,9 @@ module( const username = 'appknox'; this.server.post('/v2/forgot_password', (schema, req) => { - const reqUsername = req.requestBody.split('=')[1]; + const reqBody = JSON.parse(req.requestBody); + + const reqUsername = reqBody.username; assert.strictEqual(username, reqUsername); diff --git a/tests/integration/components/via-org-invite-test.js b/tests/integration/components/via-org-invite-test.js index 5dee7ce19..eee28a575 100644 --- a/tests/integration/components/via-org-invite-test.js +++ b/tests/integration/components/via-org-invite-test.js @@ -167,20 +167,12 @@ module( assert.expect(13); this.server.post('/invite', (_, req) => { - const body = req.requestBody; - - const data = body - .split('&') - .map((pair) => pair.split('=')) - .reduce((acc, [key, value]) => { - value = decodeURIComponent(value.replace(/\+/g, ' ')); - return { ...acc, [key]: value }; - }, {}); + const data = JSON.parse(req.requestBody); const { username, terms_accepted, password, confirm_password } = data; assert.strictEqual(username, 'test'); - assert.strictEqual(terms_accepted, 'true'); + assert.true(terms_accepted); assert.strictEqual(password, 'test@12345'); assert.strictEqual(confirm_password, 'test@12345'); diff --git a/tests/integration/components/via-partner-invite-test.js b/tests/integration/components/via-partner-invite-test.js index bdb4b4f1d..8a89f45ae 100644 --- a/tests/integration/components/via-partner-invite-test.js +++ b/tests/integration/components/via-partner-invite-test.js @@ -101,20 +101,12 @@ module( assert.expect(8); this.server.post('/v2/registration-via-invite', (_, req) => { - const body = req.requestBody; - - const data = body - .split('&') - .map((pair) => pair.split('=')) - .reduce((acc, [key, value]) => { - value = decodeURIComponent(value.replace(/\+/g, ' ')); - return { ...acc, [key]: value }; - }, {}); + const data = JSON.parse(req.requestBody); assert.strictEqual(data.username, 'test'); assert.strictEqual(data.password, 'test@12345'); assert.strictEqual(data.confirm_password, 'test@12345'); - assert.strictEqual(data.terms_accepted, 'true'); + assert.true(data.terms_accepted); return new Response(201); }); diff --git a/tests/unit/services/ajax-test.js b/tests/unit/services/ajax-test.js index 6424ee338..2d6d29f89 100644 --- a/tests/unit/services/ajax-test.js +++ b/tests/unit/services/ajax-test.js @@ -1,12 +1,99 @@ -/* eslint-disable prettier/prettier */ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; -module('Unit | Service | ajax', function(hooks) { +module('Unit | Service | ajax', function (hooks) { setupTest(hooks); + setupMirage(hooks); test('it exists', function (assert) { const service = this.owner.lookup('service:ajax'); assert.ok(service); }); + + test('it should make a GET request', async function (assert) { + const service = this.owner.lookup('service:ajax'); + const fakeResponse = { data: 'test' }; + + this.server.get(`test-url`, () => { + return fakeResponse; + }); + + const response = await service.request('test-url'); + + assert.deepEqual(response, fakeResponse); + }); + + test('it should make a POST request', async function (assert) { + assert.expect(2); + + const service = this.owner.lookup('service:ajax'); + const fakeResponse = { data: 'test post response' }; + const requestData = { key: 'value' }; + + this.server.post('test-url', (schema, request) => { + const requestBody = JSON.parse(request.requestBody); + + assert.deepEqual( + requestBody, + requestData, + 'The correct data was sent in the POST request' + ); + + return fakeResponse; + }); + + const response = await service.post('test-url', { data: requestData }); + + assert.deepEqual( + response, + fakeResponse, + 'The response matches the fake response' + ); + }); + + test('it should make a PUT request', async function (assert) { + assert.expect(2); + + const service = this.owner.lookup('service:ajax'); + const fakeResponse = { data: 'test put response' }; + const requestData = { key: 'new value' }; + + this.server.put('test-url', (schema, request) => { + const requestBody = JSON.parse(request.requestBody); + + assert.deepEqual( + requestBody, + requestData, + 'The correct data was sent in the PUT request' + ); + + return fakeResponse; + }); + + const response = await service.put('test-url', { data: requestData }); + + assert.deepEqual( + response, + fakeResponse, + 'The response matches the fake response' + ); + }); + + test('it should make a DELETE request', async function (assert) { + const service = this.owner.lookup('service:ajax'); + const fakeResponse = { data: 'test delete response' }; + + this.server.delete('test-url', () => { + return fakeResponse; + }); + + const response = await service.delete('test-url'); + + assert.deepEqual( + response, + fakeResponse, + 'The response matches the fake response' + ); + }); }); diff --git a/tsconfig.json b/tsconfig.json index 01546ea30..83fcda3de 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "baseUrl": ".", "verbatimModuleSyntax": false, // TODO: remove this later "paths": { + "fetch": ["node_modules/ember-fetch"], "irene/tests/*": ["tests/*"], "irene/mirage/*": ["mirage/*"], "irene/translations/*": ["translations/*"],