Skip to content

Commit 7659dfd

Browse files
committed
feat(admin): let instances choose which pad types are offered
Add two settings, Protected pads and Public pads, both enabled by default so existing installations are unaffected. The labels keep the vocabulary the API and the binding table already use. Enforcement is server-side, matching allow_external_pads: PadCreationService covers the API and embed-create paths, materializeTemplateInto() the templates, and PadBootstrapService guards its `binding === null` branch -- otherwise an empty .pad plus /initialize was a way around the setting. The check deliberately stays out of provisionPadId(), which also re-initialises files that already have a binding. Existing pads of a disabled type keep working; only creation is affected. Turning both off is allowed. A template carrying a disabled mode is created in the enabled mode rather than failing, and Nextcloud's own "+ New pad" entry is hidden when protected pads are off, since it always produces one. External pads stay independent. The setting decides what the app offers -- it is not a hard boundary against hand-crafted .pad files. Recovering an orphaned pad from its snapshot still re-provisions the mode recorded in the file, because rescuing existing content wins. Includes de/es/fr translations and doc updates. Closes #175.
1 parent 0751fa0 commit 7659dfd

54 files changed

Lines changed: 897 additions & 31 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,31 @@ and configure:
9595
- Etherpad API URL (optional; defaults to Base URL)
9696
- Etherpad API key (OAuth is not required; Etherpad API key auth is used)
9797
- Copy content to `.pad` file interval
98+
- Which pad types users may create (see below)
9899
- Delete-on-trash policy
99100
- External public pad policy
100101

102+
Two settings control which pad types the app offers, both enabled by default:
103+
104+
- **Protected pads** — only people who can open the `.pad` file in Nextcloud
105+
can open the pad. Created as Etherpad group pads, which require a session
106+
issued by Nextcloud.
107+
- **Public pads** — anyone with the pad link can open the pad, without a
108+
Nextcloud account.
109+
110+
Switching a type off hides its `+ New` entries and refuses new pads of that
111+
type on the regular create paths — the API create endpoints, the template
112+
flows and the first-open initialisation of a `.pad` that has no pad yet. Pads
113+
that already exist keep working either way.
114+
115+
The setting decides what the app offers; it is not a hard boundary against a
116+
user who crafts `.pad` files by hand. Recovering an orphaned `.pad` from its
117+
snapshot still re-provisions the mode recorded in that file, because rescuing
118+
existing content takes precedence.
119+
120+
Linking external public pads is governed separately by the external pad
121+
policy and is unaffected by these two settings.
122+
101123
### 5) Check iframe and cookie setup for protected pads
102124

103125
If protected pads should open inside the Nextcloud viewer iframe:

docs/api-reference.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ Base: `/apps/etherpad_nextcloud`
7171
- read-only protected share: `is_readonly_snapshot=true`, empty `url`, `snapshot_text`, and sanitized `snapshot_html`; no Etherpad session cookie
7272
- public/external pad share: regular public Etherpad URL
7373

74+
Admins can switch either pad type off (see the admin settings). Creating a pad
75+
of a disabled type is refused with `403` by `POST /pads`,
76+
`POST /pads/create-by-parent`, `POST /pads/from-template` and the
77+
`initialize` endpoints; pads that already exist are unaffected. Templates
78+
carrying a disabled mode are created in the enabled mode instead of failing.
79+
80+
`POST /pads/from-url` is deliberately exempt: external pads are governed
81+
solely by the separate external-pad policy, not by these two settings.
82+
7483
- `POST /api/v1/pads`
7584
- Controller: `PadCreateController::create`
7685
- Params:

docs/architecture.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ Etherpad is the editing source of truth; the `.pad` file acts as binding storage
2929
- Revision metadata and snapshot body structure (`[TEXT]`, `[HTML-BEGIN]`, `[HTML-END]`).
3030
- `lib/Service/PadSessionService.php`
3131
- Session-cookie flow for protected GroupPads.
32+
- `lib/Service/PadTypePolicy.php`
33+
- Which pad types the instance offers (both enabled by default).
34+
- Guards creation only; existing pads of a disabled type keep working.
35+
- Resolves a template's access mode to an enabled one instead of failing.
3236
- `lib/Service/ConsistencyCheckService.php`
3337
- Optional admin integrity scan:
3438
- bindings without file
@@ -86,7 +90,7 @@ checked-in runtime assets in `js/`.
8690

8791
### 1) Create
8892

89-
1. `PadCreateController::create` creates an Etherpad pad (public or protected/group).
93+
1. `PadCreateController::create` creates an Etherpad pad (public or protected/group). `PadCreationService` asks `PadTypePolicy` first and refuses a pad type the admin switched off; the check sits in the create paths rather than in `PadBootstrapService::provisionPadId`, which also serves existing files.
9094
2. Creates the `.pad` file.
9195
3. Writes initial frontmatter.
9296
4. Creates DB binding.
@@ -249,6 +253,7 @@ Primary flow (native viewer when available):
249253
- `+ Neu` integration for `Public pad` with runtime capability checks:
250254
- modern API: `addNewFileMenuEntry` / `getNewFileMenu().registerEntry`
251255
- legacy API fallback: `OC.Plugins.register('OCA.Files.NewFileMenu', ...)`
256+
- The `Public pad` entry follows the admin setting, read from initial state. `Public pad from URL` is always registered; the external-pad policy is enforced server-side when the create call arrives.
252257
- `src/files/public-share-pad-links.js`
253258
- Public-share click interception for download links that need remapping to the pad viewer.
254259
- Authenticated Files routes intentionally do not use global click interception.

docs/etherpad-integration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ Important:
3737
- GroupPad ID (`g.<group>$<name>`).
3838
- Access only with a valid Etherpad session (`sessionID` cookie).
3939

40+
Either type can be switched off in the admin settings, which stops new pads of
41+
that type from being created. Existing pads keep opening regardless, so the
42+
setting never cuts anyone off from content.
43+
4044
## Session Flow (protected)
4145

4246
Implemented in `lib/Service/PadSessionService.php`.

docs/templates.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Response shape on success (200):
8080

8181
Error responses:
8282
- **400** — template is not a `.pad`, template is external (`ext.*`), template is empty, target path invalid
83+
- **403** — no pad type is enabled in the admin settings, so nothing can be created
8384
- **404** — template file ID does not resolve in the user's userspace
8485
- **409** — target filename collides with an existing file (`A file with this name already exists.`)
8586
- **500** — Etherpad unreachable or other unexpected failure
@@ -90,3 +91,4 @@ Error responses:
9091
- **Failed template materialisation falls back to a blank pad.** If anything in the listener throws (binding race, Etherpad unreachable, malformed template), the byte-copy NC made is wiped and the new file behaves like a normal empty `.pad` — the regular missing-frontmatter init kicks in on first open.
9192
- **Placeholder substitution applies to both the plain-text and the HTML snapshot in the body**. If a placeholder ends up inside an HTML attribute (`<a href="{{date}}">`), it gets resolved too — keep placeholders in human-readable locations to avoid surprises.
9293
- **No template registry** — every `.pad` in the user's *Templates* folder is a candidate. There's no separate "is a template" flag.
94+
- **A template keeps its own access mode**, unless the admin switched that pad type off. In that case the pad is created in the enabled mode instead of failing, so the template's content still lands. With no pad type enabled at all, template creation is refused.
Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)