feat: add support for disabling specific features in the PDF Editor
This commit is contained in:
10
README.md
10
README.md
@@ -871,6 +871,16 @@ docker run -d -p 3000:8080 \
|
|||||||
|
|
||||||
Both methods can be combined — the lists are merged. For the full list of tool IDs, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-specific-tools).
|
Both methods can be combined — the lists are merged. For the full list of tool IDs, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-specific-tools).
|
||||||
|
|
||||||
|
You can also disable specific features inside the PDF Editor (e.g., redaction, forms) without disabling the entire editor. Add `editorDisabledCategories` to your `config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"editorDisabledCategories": ["redaction"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For the full list of editor categories, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-editor-features).
|
||||||
|
|
||||||
### 🔒 Security Features
|
### 🔒 Security Features
|
||||||
|
|
||||||
BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security:
|
BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security:
|
||||||
|
|||||||
@@ -204,6 +204,45 @@ services:
|
|||||||
|
|
||||||
Both methods can be combined — the lists are merged. If a tool appears in either, it is disabled.
|
Both methods can be combined — the lists are merged. If a tool appears in either, it is disabled.
|
||||||
|
|
||||||
|
#### Disabling Editor Features
|
||||||
|
|
||||||
|
You can also disable specific features inside the PDF Editor (e.g., redaction, annotations, forms) without disabling the entire editor tool. Add `editorDisabledCategories` to your `config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"editorDisabledCategories": ["redaction", "annotation-stamp"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Full list of editor categories</summary>
|
||||||
|
|
||||||
|
**Zoom:** `zoom`, `zoom-in`, `zoom-out`, `zoom-fit-page`, `zoom-fit-width`, `zoom-marquee`, `zoom-level`
|
||||||
|
|
||||||
|
**Annotation:** `annotation`, `annotation-markup`, `annotation-highlight`, `annotation-underline`, `annotation-strikeout`, `annotation-squiggly`, `annotation-ink`, `annotation-text`, `annotation-stamp`
|
||||||
|
|
||||||
|
**Shapes:** `annotation-shape`, `annotation-rectangle`, `annotation-circle`, `annotation-line`, `annotation-arrow`, `annotation-polygon`, `annotation-polyline`
|
||||||
|
|
||||||
|
**Form:** `form`, `form-textfield`, `form-checkbox`, `form-radio`, `form-select`, `form-listbox`, `form-fill-mode`
|
||||||
|
|
||||||
|
**Redaction:** `redaction`, `redaction-area`, `redaction-text`, `redaction-apply`, `redaction-clear`
|
||||||
|
|
||||||
|
**Document:** `document`, `document-open`, `document-close`, `document-print`, `document-capture`, `document-export`, `document-fullscreen`, `document-protect`
|
||||||
|
|
||||||
|
**Page:** `page`, `spread`, `rotate`, `scroll`, `navigation`
|
||||||
|
|
||||||
|
**Panel:** `panel`, `panel-sidebar`, `panel-search`, `panel-comment`
|
||||||
|
|
||||||
|
**Tools:** `tools`, `pan`, `pointer`, `capture`
|
||||||
|
|
||||||
|
**Selection:** `selection`, `selection-copy`
|
||||||
|
|
||||||
|
**History:** `history`, `history-undo`, `history-redo`
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Categories are hierarchical — disabling a parent (e.g., `annotation`) disables all its children.
|
||||||
|
|
||||||
### Custom WASM URLs (Air-Gapped / Self-Hosted)
|
### Custom WASM URLs (Air-Gapped / Self-Hosted)
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
|
|||||||
@@ -164,7 +164,9 @@ docker run -d -p 3000:8080 \
|
|||||||
ghcr.io/alam00000/bentopdf:latest
|
ghcr.io/alam00000/bentopdf:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Both methods can be combined — the lists are merged. See the [Docker guide](/self-hosting/docker#disabling-specific-tools) for full details.
|
Both methods can be combined — the lists are merged.
|
||||||
|
|
||||||
|
You can also disable specific features inside the PDF Editor (e.g., redaction) without disabling the entire tool by adding `editorDisabledCategories` to `config.json`. See the [Docker guide](/self-hosting/docker#disabling-editor-features) for the full list of categories.
|
||||||
|
|
||||||
## Deployment Guides
|
## Deployment Guides
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { showAlert, showLoader, hideLoader } from '../ui.js';
|
|||||||
import { formatBytes, downloadFile } from '../utils/helpers.js';
|
import { formatBytes, downloadFile } from '../utils/helpers.js';
|
||||||
import { makeUniqueFileKey } from '../utils/deduplicate-filename.js';
|
import { makeUniqueFileKey } from '../utils/deduplicate-filename.js';
|
||||||
import { batchDecryptIfNeeded } from '../utils/password-prompt.js';
|
import { batchDecryptIfNeeded } from '../utils/password-prompt.js';
|
||||||
|
import { getEditorDisabledCategories } from '../utils/disabled-tools.js';
|
||||||
|
|
||||||
const embedPdfWasmUrl = new URL(
|
const embedPdfWasmUrl = new URL(
|
||||||
'embedpdf-snippet/dist/pdfium.wasm',
|
'embedpdf-snippet/dist/pdfium.wasm',
|
||||||
@@ -130,7 +131,9 @@ async function handleFiles(files: FileList) {
|
|||||||
pdfWrapper.classList.remove('hidden');
|
pdfWrapper.classList.remove('hidden');
|
||||||
|
|
||||||
const { default: EmbedPDF } = await import('embedpdf-snippet');
|
const { default: EmbedPDF } = await import('embedpdf-snippet');
|
||||||
|
const disabledCategories = getEditorDisabledCategories();
|
||||||
viewerInstance = EmbedPDF.init({
|
viewerInstance = EmbedPDF.init({
|
||||||
|
disabledCategories,
|
||||||
type: 'container',
|
type: 'container',
|
||||||
target: pdfContainer,
|
target: pdfContainer,
|
||||||
worker: true,
|
worker: true,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export interface AppConfig {
|
export interface AppConfig {
|
||||||
disabledTools?: string[];
|
disabledTools?: string[];
|
||||||
|
editorDisabledCategories?: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { AppConfig } from '@/types';
|
|||||||
|
|
||||||
const disabledToolsSet = new Set<string>(__DISABLED_TOOLS__);
|
const disabledToolsSet = new Set<string>(__DISABLED_TOOLS__);
|
||||||
let runtimeConfigLoaded = false;
|
let runtimeConfigLoaded = false;
|
||||||
|
let editorDisabledCategories: string[] = [];
|
||||||
|
|
||||||
export async function loadRuntimeConfig(): Promise<void> {
|
export async function loadRuntimeConfig(): Promise<void> {
|
||||||
if (runtimeConfigLoaded) return;
|
if (runtimeConfigLoaded) return;
|
||||||
@@ -21,6 +22,11 @@ export async function loadRuntimeConfig(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Array.isArray(config.editorDisabledCategories)) {
|
||||||
|
editorDisabledCategories = config.editorDisabledCategories.filter(
|
||||||
|
(c): c is string => typeof c === 'string'
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +42,10 @@ export function getToolIdFromPath(): string | null {
|
|||||||
return withoutExt?.[1] ?? null;
|
return withoutExt?.[1] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getEditorDisabledCategories(): string[] {
|
||||||
|
return editorDisabledCategories;
|
||||||
|
}
|
||||||
|
|
||||||
export function isCurrentPageDisabled(): boolean {
|
export function isCurrentPageDisabled(): boolean {
|
||||||
const toolId = getToolIdFromPath();
|
const toolId = getToolIdFromPath();
|
||||||
if (!toolId) return false;
|
if (!toolId) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user