diff --git a/.changeset/heavy-carrots-reflect.md b/.changeset/heavy-carrots-reflect.md new file mode 100644 index 000000000000..1d85ebe67e69 --- /dev/null +++ b/.changeset/heavy-carrots-reflect.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": major +--- + +Removes private App installation via URL method following a deprecation warning. diff --git a/apps/meteor/client/views/marketplace/AppInstallPage.tsx b/apps/meteor/client/views/marketplace/AppInstallPage.tsx index 5168f978b4bc..68ecc313991a 100644 --- a/apps/meteor/client/views/marketplace/AppInstallPage.tsx +++ b/apps/meteor/client/views/marketplace/AppInstallPage.tsx @@ -1,6 +1,6 @@ -import { Button, ButtonGroup, Icon, Field, FieldGroup, FieldLabel, FieldRow, TextInput, Callout } from '@rocket.chat/fuselage'; +import { Button, ButtonGroup, Field, FieldGroup, FieldLabel, FieldRow, TextInput } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; -import { useTranslation, useRouter, useSearchParameter } from '@rocket.chat/ui-contexts'; +import { useTranslation, useRouter } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; import { useForm, Controller } from 'react-hook-form'; @@ -8,17 +8,13 @@ import { Page, PageHeader, PageScrollableContent } from '../../components/Page'; import { useSingleFileInput } from '../../hooks/useSingleFileInput'; import { useInstallApp } from './hooks/useInstallApp'; -const PLACEHOLDER_URL = 'https://rocket.chat/apps/package.zip'; - const AppInstallPage = () => { const t = useTranslation(); const router = useRouter(); - const queryUrl = useSearchParameter('url'); - - const { control, setValue, watch } = useForm<{ file: File; url: string }>({ defaultValues: { url: queryUrl || '' } }); - const { file, url } = watch(); - const { install, isInstalling } = useInstallApp(file, url); + const { control, setValue, watch } = useForm<{ file: File }>(); + const { file } = watch(); + const { install, isInstalling } = useInstallApp(file); const [handleUploadButtonClick] = useSingleFileInput((value) => setValue('file', value), 'app'); @@ -32,7 +28,6 @@ const AppInstallPage = () => { }); }, [router]); - const urlField = useUniqueId(); const fileField = useUniqueId(); return ( @@ -40,21 +35,6 @@ const AppInstallPage = () => { - - {t('App_Url_to_Install_From')} - - {t('App_Installation_Deprecation')} - - - ( - } {...field} /> - )} - /> - - {t('App_Url_to_Install_From_File')} @@ -79,7 +59,7 @@ const AppInstallPage = () => { - diff --git a/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx b/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx index 3b784e24c375..a544413bb6a5 100644 --- a/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx @@ -1,5 +1,5 @@ import type { App, AppPermission } from '@rocket.chat/core-typings'; -import { useRouter, useSetModal, useUpload, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useRouter, useSetModal, useUpload } from '@rocket.chat/ui-contexts'; import { useMutation } from '@tanstack/react-query'; import React, { useCallback, useState } from 'react'; @@ -15,7 +15,7 @@ import { handleInstallError } from '../helpers/handleInstallError'; import { getManifestFromZippedApp } from '../lib/getManifestFromZippedApp'; import { useAppsCountQuery } from './useAppsCountQuery'; -export const useInstallApp = (file: File, url: string): { install: () => void; isInstalling: boolean } => { +export const useInstallApp = (file: File): { install: () => void; isInstalling: boolean } => { const reloadAppsList = useAppsReload(); const openExternalLink = useExternalLink(); const setModal = useSetModal(); @@ -28,9 +28,6 @@ export const useInstallApp = (file: File, url: string): { install: () => void; i const uploadAppEndpoint = useUpload('/apps'); const uploadUpdateEndpoint = useUpload('/apps/update'); - // TODO: This function should not be called in a next major version, it will be changed by an endpoint deprecation. - const downloadPrivateAppFromUrl = useEndpoint('POST', '/apps'); - const [isInstalling, setInstalling] = useState(false); const { mutate: sendFile } = useMutation( @@ -102,17 +99,6 @@ export const useInstallApp = (file: File, url: string): { install: () => void; i await handleAppPermissionsReview(permissions, appFile); }; - /** @deprecated */ - const getAppFile = async (): Promise => { - try { - const { buff } = (await downloadPrivateAppFromUrl({ url, downloadOnly: true })) as { buff: { data: ArrayLike } }; - - return new File([Uint8Array.from(buff.data)], 'app.zip', { type: 'application/zip' }); - } catch (error) { - handleInstallError(error as Error); - } - }; - const extractManifestFromAppFile = async (appFile: File) => { try { return getManifestFromZippedApp(appFile); @@ -122,19 +108,13 @@ export const useInstallApp = (file: File, url: string): { install: () => void; i }; const install = async () => { - let appFile: File | undefined; - setInstalling(true); if (!appCountQuery.data) { return cancelAction(); } - if (!file) { - appFile = await getAppFile(); - } else { - appFile = file; - } + const appFile = file; if (!appFile) { return cancelAction(); @@ -157,7 +137,7 @@ export const useInstallApp = (file: File, url: string): { install: () => void; i limit={appCountQuery.data.limit} appName={manifest.name} handleClose={cancelAction} - handleConfirm={() => uploadFile(appFile as File, manifest)} + handleConfirm={() => uploadFile(appFile, manifest)} handleEnableUnlimitedApps={() => { openExternalLink(manageSubscriptionUrl); setModal(null); diff --git a/apps/meteor/ee/server/apps/communication/rest.ts b/apps/meteor/ee/server/apps/communication/rest.ts index 3eed45f4ddad..f3420d2ccce9 100644 --- a/apps/meteor/ee/server/apps/communication/rest.ts +++ b/apps/meteor/ee/server/apps/communication/rest.ts @@ -328,12 +328,6 @@ export class AppsRestApi { orchestrator.getRocketChatLogger().error('Error getting the app from url:', e.response.data); return API.v1.internalError(); } - - if (this.bodyParams.downloadOnly) { - apiDeprecationLogger.parameter(this.request.route, 'downloadOnly', '7.0.0', this.response); - - return API.v1.success({ buff }); - } } else if ('appId' in this.bodyParams && this.bodyParams.appId && this.bodyParams.marketplace && this.bodyParams.version) { const baseUrl = orchestrator.getMarketplaceUrl(); diff --git a/packages/rest-typings/src/apps/index.ts b/packages/rest-typings/src/apps/index.ts index f037f6b59c74..b25297a61e7a 100644 --- a/packages/rest-typings/src/apps/index.ts +++ b/packages/rest-typings/src/apps/index.ts @@ -248,9 +248,8 @@ export type AppsEndpoints = { version: string; permissionsGranted?: IPermission[]; url?: string; - downloadOnly?: boolean; } - | { url: string; downloadOnly?: boolean }, + | { url: string }, ): | { app: App;