Skip to content

Commit

Permalink
Merge pull request #9033 from weseek/imprv/149843-152624-disable-bulk…
Browse files Browse the repository at this point in the history
…-export-when-fs-not-s3-or-gcs

Imprv/149843 152624 disable bulk export when fs not s3 or gcs
  • Loading branch information
arafubeatbox authored Sep 2, 2024
2 parents 59b9233 + 49f8b4a commit 6d5f66a
Show file tree
Hide file tree
Showing 13 changed files with 76 additions and 27 deletions.
1 change: 1 addition & 0 deletions apps/app/public/static/locales/en_US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@
"bulk_export_started": "Please wait a moment...",
"bulk_export_download_expired": "Download period has expired",
"bulk_export_job_expired": "Export process was canceled because it took too long",
"bulk_export_only_available_for": "Only available for AWS or GCP",
"export_in_progress": "Export in progress",
"export_in_progress_explanation": "Export with the same format is already in progress. Would you like to restart to export the latest page contents?",
"export_cancel_warning": "The export in progress will be canceled",
Expand Down
1 change: 1 addition & 0 deletions apps/app/public/static/locales/fr_FR/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@
"bulk_export_started": "Patientez s'il-vous-plait...",
"bulk_export_download_expired": "La période de téléchargement a expiré",
"bulk_export_job_expired": "Le traitement a été interrompu car le temps d'exportation était trop long",
"bulk_export_only_available_for": "Uniquement disponible pour AWS ou GCP",
"export_in_progress": "Exportation en cours",
"export_in_progress_explanation": "L'exportation avec le même format est déjà en cours. Souhaitez-vous redémarrer pour exporter le dernier contenu de la page ?",
"export_cancel_warning": "L'export en cours sera annulé",
Expand Down
1 change: 1 addition & 0 deletions apps/app/public/static/locales/ja_JP/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@
"bulk_export_started": "ただいま準備中です...",
"bulk_export_download_expired": "ダウンロード期限が切れました",
"bulk_export_job_expired": "エクスポート時間が長すぎるため、処理が中断されました",
"bulk_export_only_available_for": "AWS と GCP のみ対応しています",
"export_in_progress": "エクスポート進行中",
"export_in_progress_explanation": "既に同じ形式でのエクスポートが進行中です。最新のページ内容でエクスポートを最初からやり直しますか?",
"export_cancel_warning": "進行中のエクスポートはキャンセルされます",
Expand Down
1 change: 1 addition & 0 deletions apps/app/public/static/locales/zh_CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,7 @@
"bulk_export_started": "目前我们正在准备...",
"bulk_export_download_expired": "下载期限已过",
"bulk_export_job_expired": "由于导出时间太长,处理被中断",
"bulk_export_only_available_for": "仅适用于 AWS 或 GCP",
"export_in_progress": "导出正在进行中",
"export_in_progress_explanation": "已在进行相同格式的导出。您要重新启动以导出最新的页面内容吗?",
"export_cancel_warning": "正在进行的导出将被取消",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslation } from 'next-i18next';

import AdminAppContainer from '~/client/services/AdminAppContainer';
import { toastSuccess, toastError } from '~/client/util/toastr';
import { FileUploadType } from '~/interfaces/file-uploader';

import { withUnstatedContainers } from '../../UnstatedUtils';
import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
Expand All @@ -16,9 +17,6 @@ import type { AzureSettingMoleculeProps } from './AzureSetting';
import { GcsSettingMolecule } from './GcsSetting';
import type { GcsSettingMoleculeProps } from './GcsSetting';


const fileUploadTypes = ['aws', 'gcs', 'azure', 'gridfs', 'local'] as const;

type FileUploadSettingMoleculeProps = {
fileUploadType: string
isFixedFileUploadByEnvVar: boolean
Expand All @@ -45,7 +43,7 @@ export const FileUploadSettingMolecule = React.memo((props: FileUploadSettingMol
</label>

<div className="col-md-6 py-2">
{fileUploadTypes.map((type) => {
{Object.values(FileUploadType).map((type) => {
return (
<div key={type} className="form-check form-check-inline">
<input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import dynamic from 'next/dynamic';
import Link from 'next/link';
import { useRouter } from 'next/router';
import Sticky from 'react-stickynode';
import { DropdownItem, UncontrolledTooltip } from 'reactstrap';
import { Tooltip, DropdownItem, UncontrolledTooltip } from 'reactstrap';

import { exportAsMarkdown, updateContentWidth, syncLatestRevisionBody } from '~/client/services/page-operation';
import { toastSuccess, toastError, toastWarning } from '~/client/util/toastr';
Expand All @@ -25,7 +25,7 @@ import type { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from
import { useShouldExpandContent } from '~/services/layout/use-should-expand-content';
import {
useCurrentPathname,
useCurrentUser, useIsGuestUser, useIsReadOnlyUser, useIsLocalAccountRegistrationEnabled, useIsSharedUser, useShareLinkId,
useCurrentUser, useIsGuestUser, useIsReadOnlyUser, useIsPageBulkExportEnabled, useIsLocalAccountRegistrationEnabled, useIsSharedUser, useShareLinkId,
} from '~/stores-universal/context';
import { useEditorMode } from '~/stores-universal/ui';
import {
Expand Down Expand Up @@ -77,13 +77,16 @@ const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element
const { data: isGuestUser } = useIsGuestUser();
const { data: isReadOnlyUser } = useIsReadOnlyUser();
const { data: isSharedUser } = useIsSharedUser();
const { data: isPageBulkExportEnabled } = useIsPageBulkExportEnabled();

const { open: openPresentationModal } = usePagePresentationModal();
const { open: openAccessoriesModal } = usePageAccessoriesModal();
const { open: openPageBulkExportSelectModal } = usePageBulkExportSelectModal();

const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);

const [isBulkExportTooltipOpen, setIsBulkExportTooltipOpen] = useState(false);

const syncLatestRevisionBodyHandler = useCallback(async() => {
// eslint-disable-next-line no-alert
const answer = window.confirm(t('sync-latest-revision-body.confirm'));
Expand Down Expand Up @@ -141,13 +144,25 @@ const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element
</DropdownItem>

{/* Bulk export */}
<DropdownItem
onClick={openPageBulkExportSelectModal}
className="grw-page-control-dropdown-item"
<span id="bulkExportDropdownItem">
<DropdownItem
disabled={!isPageBulkExportEnabled}
onClick={openPageBulkExportSelectModal}
className="grw-page-control-dropdown-item"
>
<span className="material-symbols-outlined me-1 grw-page-control-dropdown-icon">cloud_download</span>
{t('page_export.bulk_export')}
</DropdownItem>
</span>
<Tooltip
placement="left"
isOpen={isBulkExportTooltipOpen}
// Tooltip cannot be activated when target is disabled so set the target to wrapper span
target="bulkExportDropdownItem"
toggle={() => setIsBulkExportTooltipOpen(!isBulkExportTooltipOpen)}
>
<span className="material-symbols-outlined me-1 grw-page-control-dropdown-icon">cloud_download</span>
{t('page_export.bulk_export')}
</DropdownItem>
{t('page_export.bulk_export_only_available_for')}
</Tooltip>

<DropdownItem divider />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type {
IAttachment, IPage, IRevision, IUser, Ref,
} from '@growi/core';

import { FileUploadTypeForEnvVar } from '~/interfaces/file-uploader';

export const PageBulkExportFormat = {
md: 'md',
pdf: 'pdf',
Expand Down Expand Up @@ -45,3 +47,5 @@ export interface IPageBulkExportPageSnapshot {
path: string, // page path when export was stared
revision: Ref<IRevision>, // page revision when export was stared
}

export const PageBulkExportEnabledFileUploadTypes = [FileUploadTypeForEnvVar.aws, FileUploadTypeForEnvVar.gcs, FileUploadTypeForEnvVar.gcp] as const;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { configManager } from '~/server/service/config-manager';
import CronService from '~/server/service/cron';
import loggerFactory from '~/utils/logger';

import { PageBulkExportJobInProgressStatus, PageBulkExportJobStatus } from '../../interfaces/page-bulk-export';
import { PageBulkExportEnabledFileUploadTypes, PageBulkExportJobInProgressStatus, PageBulkExportJobStatus } from '../../interfaces/page-bulk-export';
import type { PageBulkExportJobDocument } from '../models/page-bulk-export-job';
import PageBulkExportJob from '../models/page-bulk-export-job';

Expand All @@ -29,6 +29,9 @@ class PageBulkExportJobCronService extends CronService {
}

override async executeJob(): Promise<void> {
const isPageBulkExportEnabled = PageBulkExportEnabledFileUploadTypes.includes(configManager.getConfig('crowi', 'app:fileUploadType'));
if (!isPageBulkExportEnabled) return;

await this.deleteExpiredExportJobs();
await this.deleteDownloadExpiredExportJobs();
await this.deleteFailedExportJobs();
Expand Down
28 changes: 28 additions & 0 deletions apps/app/src/interfaces/file-uploader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// file upload types actually supported by the app
export const FileUploadType = {
aws: 'aws',
gcs: 'gcs',
azure: 'azure',
gridfs: 'gridfs',
local: 'local',
} as const;

export type FileUploadType = typeof FileUploadType[keyof typeof FileUploadType]

// file upload type strings you can specify in the env variable
export const FileUploadTypeForEnvVar = {
...FileUploadType,
mongo: 'mongo',
mongodb: 'mongodb',
gcp: 'gcp',
} as const;

export type FileUploadTypeForEnvVar = typeof FileUploadTypeForEnvVar[keyof typeof FileUploadTypeForEnvVar]

// mapping from env variable to actual module name
export const EnvToModuleMappings = {
...FileUploadTypeForEnvVar,
mongo: 'gridfs',
mongodb: 'gridfs',
gcp: 'gcs',
} as const;
6 changes: 5 additions & 1 deletion apps/app/src/pages/[[...path]].page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import superjson from 'superjson';
import { BasicLayout } from '~/components/Layout/BasicLayout';
import { PageView } from '~/components/PageView/PageView';
import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
import { PageBulkExportEnabledFileUploadTypes } from '~/features/page-bulk-export/interfaces/page-bulk-export';
import { SupportedAction, type SupportedActionType } from '~/interfaces/activity';
import type { CrowiRequest } from '~/interfaces/crowi-request';
import { RegistrationMode } from '~/interfaces/registration-mode';
Expand All @@ -42,7 +43,7 @@ import {
useCsrfToken, useIsSearchScopeChildrenAsDefault, useIsEnabledMarp, useCurrentPathname,
useIsSlackConfigured, useRendererConfig, useGrowiCloudUri,
useIsAllReplyShown, useIsContainerFluid, useIsNotCreatable,
useIsUploadAllFileAllowed, useIsUploadEnabled,
useIsUploadAllFileAllowed, useIsUploadEnabled, useIsPageBulkExportEnabled,
useElasticsearchMaxBodyLengthToIndex,
useIsLocalAccountRegistrationEnabled,
} from '~/stores-universal/context';
Expand Down Expand Up @@ -177,6 +178,7 @@ type Props = CommonProps & {
isContainerFluid: boolean,
isUploadEnabled: boolean,
isUploadAllFileAllowed: boolean,
isPageBulkExportEnabled: boolean,
isEnabledStaleNotification: boolean,
isEnabledAttachTitleHeader: boolean,
// isEnabledLinebreaks: boolean,
Expand Down Expand Up @@ -239,6 +241,7 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {

useIsUploadAllFileAllowed(props.isUploadAllFileAllowed);
useIsUploadEnabled(props.isUploadEnabled);
useIsPageBulkExportEnabled(props.isPageBulkExportEnabled);

useIsLocalAccountRegistrationEnabled(props.isLocalAccountRegistrationEnabled);

Expand Down Expand Up @@ -560,6 +563,7 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
props.disableLinkSharing = configManager.getConfig('crowi', 'security:disableLinkSharing');
props.isUploadAllFileAllowed = crowi.fileUploadService.getFileUploadEnabled();
props.isUploadEnabled = crowi.fileUploadService.getIsUploadable();
props.isPageBulkExportEnabled = PageBulkExportEnabledFileUploadTypes.includes(configManager.getConfig('crowi', 'app:fileUploadType'));

props.isLocalAccountRegistrationEnabled = crowi.passportService.isLocalStrategySetup
&& configManager.getConfig('crowi', 'security:registrationMode') !== RegistrationMode.CLOSED;
Expand Down
1 change: 0 additions & 1 deletion apps/app/src/server/routes/apiv3/app-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ module.exports = (crowi) => {

});


/**
* @swagger
*
Expand Down
14 changes: 2 additions & 12 deletions apps/app/src/server/service/file-uploader/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EnvToModuleMappings } from '~/interfaces/file-uploader';
import type Crowi from '~/server/crowi';
import loggerFactory from '~/utils/logger';

Expand All @@ -9,19 +10,8 @@ export type { FileUploader } from './file-uploader';

const logger = loggerFactory('growi:service:FileUploaderServise');

const envToModuleMappings = {
aws: 'aws',
local: 'local',
mongo: 'gridfs',
mongodb: 'gridfs',
gridfs: 'gridfs',
gcp: 'gcs',
gcs: 'gcs',
azure: 'azure',
};

export const getUploader = (crowi: Crowi): FileUploader => {
const method = envToModuleMappings[configManager.getConfig('crowi', 'app:fileUploadType')];
const method = EnvToModuleMappings[configManager.getConfig('crowi', 'app:fileUploadType')];
const modulePath = `./${method}`;
const uploader = require(modulePath)(crowi);

Expand Down
4 changes: 4 additions & 0 deletions apps/app/src/stores-universal/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ export const useIsUploadAllFileAllowed = (initialData?: boolean): SWRResponse<bo
return useContextSWR('isUploadAllFileAllowed', initialData);
};

export const useIsPageBulkExportEnabled = (initialData?: boolean): SWRResponse<boolean, Error> => {
return useContextSWR('isPageBulkExportEnabled', initialData);
};

export const useShowPageLimitationL = (initialData?: number): SWRResponse<number, Error> => {
return useContextSWR('showPageLimitationL', initialData);
};
Expand Down

0 comments on commit 6d5f66a

Please sign in to comment.