-
Notifications
You must be signed in to change notification settings - Fork 4
feat(integration-xwiki): XwikiProvider — external, OpenConnector-backed (leaf, backend) #1493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
40646ff
feat(integration-xwiki): XwikiProvider — external, OpenConnector-back…
rubenvdlinde bc64f40
docs(integration-xwiki): mark leaf tasks done; record cross-repo PRs …
rubenvdlinde b673f7e
docs(integration-xwiki): refine OpenConnector source template from li…
rubenvdlinde 0eb45ab
docs(integration-xwiki): reconcile design.md + proposal.md with the a…
rubenvdlinde 5f54c9f
feat(XwikiProvider): accept XWiki's raw REST envelopes (pageSummaries…
rubenvdlinde aab25e2
feat(integration): unwrap the OpenConnector CallLog body + send Accep…
rubenvdlinde f8b0e24
fix(integration-xwiki): address review feedback from PR #1493
rubenvdlinde File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| # OpenConnector source template — XWiki | ||
| # | ||
| # Import this into OpenConnector (Settings → OpenConnector → Sources → | ||
| # Import) and fill in the `location` + auth fields for your XWiki | ||
| # instance. OpenRegister's `XwikiProvider` (id: `xwiki`, group: | ||
| # `external`) routes all of its CRUD through this source via | ||
| # ExternalIntegrationRouter; it never holds credentials itself. | ||
| # | ||
| # (The repo's `config/` directory is gitignored, so this template | ||
| # lives under docs/Integrations/ — copy it to wherever your | ||
| # OpenConnector instance imports source definitions from.) | ||
| # | ||
| # XWiki version notes: | ||
| # - 5.x / 10.x+ / 14.x+ all expose a REST API under /rest. The | ||
| # mapping below uses the generic page endpoints; OpenConnector's | ||
| # adapter normalises field-name drift across versions. | ||
| # - Authentication is customer-dependent: HTTP Basic works on every | ||
| # version; OAuth2 (via the xwiki-platform-oidc extension) is | ||
| # available on newer instances. Pick ONE of the `auth` blocks | ||
| # below and delete the other. | ||
| # | ||
| # Spec: openspec/changes/integration-xwiki/design.md | ||
| # - AD-1: detail-page preview is text-only — request the | ||
| # already-rendered HTML, the @conduction/nextcloud-vue widget | ||
| # strips it to text and truncates to ~500 chars; macros are NEVER | ||
| # executed in the preview. | ||
| # - AD-2: a page may be linked by full XWiki URL or by a `Space.Page` | ||
| # path — the `create` endpoint resolves both to canonical. | ||
| # - AD-3: rows carry a `breadcrumb` so the UI can disambiguate | ||
| # same-titled pages in different spaces. | ||
|
|
||
| source: | ||
| # Stable id — MUST be `xwiki` (matches XwikiProvider::getOpenConnectorSource()). | ||
| reference: xwiki | ||
| name: XWiki | ||
| description: >- | ||
| XWiki pages linked to OpenRegister objects. Surfaced as the | ||
| "Articles" integration (sidebar tab + dashboard/detail widgets). | ||
| type: api | ||
|
|
||
| # Base URL of the XWiki REST API. Example for a wiki at | ||
| # https://wiki.example.org with the default "xwiki" wiki: | ||
| # https://wiki.example.org/rest/wikis/xwiki | ||
| location: "https://wiki.example.org/rest/wikis/xwiki" | ||
|
|
||
| # --------------------------------------------------------------- | ||
| # Authentication — keep exactly ONE of the two blocks below. | ||
| # --------------------------------------------------------------- | ||
|
|
||
| # Option A — HTTP Basic (works on all XWiki versions). | ||
| auth: | ||
| type: basic | ||
| username: "${XWIKI_USERNAME}" | ||
| password: "${XWIKI_PASSWORD}" | ||
|
|
||
| # Option B — OAuth2 (xwiki-platform-oidc; newer instances only). | ||
| # auth: | ||
| # type: oauth2 | ||
| # grantType: client_credentials | ||
| # tokenUrl: "https://wiki.example.org/oidc/token" | ||
| # clientId: "${XWIKI_OIDC_CLIENT_ID}" | ||
| # clientSecret: "${XWIKI_OIDC_CLIENT_SECRET}" | ||
| # scope: "openid profile" | ||
|
|
||
| headers: | ||
| Accept: application/json | ||
|
|
||
| # --------------------------------------------------------------- | ||
| # Endpoint mapping consumed by XwikiProvider. The provider sends | ||
| # the object context as query params (register / schema / object) | ||
| # plus optional _search / _limit / _page; OpenConnector resolves | ||
| # those to the appropriate XWiki REST calls and normalises the | ||
| # response rows to { reference, title, space, page, breadcrumb, | ||
| # url, content }. | ||
| # --------------------------------------------------------------- | ||
| # | ||
| # XWiki REST shape — verified against xwiki:lts 17.10 (Tomcat, ROOT | ||
| # context, REST at `/rest/`): | ||
| # GET /rest/wikis/xwiki/spaces/{Space}/pages/{Page} → | ||
| # { id: "xwiki:Space.Page", space, name, title, xwikiAbsoluteUrl, | ||
| # content (RAW xwiki/2.1 syntax — NOT rendered HTML), | ||
| # hierarchy: { items: [{ label, name, type: wiki|space|document, | ||
| # url }] }, version, modified, … } | ||
| # | ||
| # Two things to get right when wiring the response mapping: | ||
| # 1. AD-3 breadcrumb — XWiki's `hierarchy.items[].label` IS the | ||
| # native breadcrumb ("xwiki" / "Sandbox" / "IntegrationTest"). | ||
| # Map `breadcrumb` from it. (If you don't, OpenRegister's | ||
| # XwikiProvider derives a coarse one from space + title.) | ||
| # 2. AD-1 preview content — the REST `content` field is RAW wiki | ||
| # syntax, not HTML. For a clean text preview, fetch the | ||
| # already-rendered page body from | ||
| # GET /bin/get/{Space}/{Page}?xpage=plain (→ HTML) | ||
| # (XWiki executes the page's macros server-side, in XWiki's own | ||
| # sandbox — they are NEVER executed inside Nextcloud; the widget | ||
| # only ever reads the text content) and map that to `content`. | ||
| # If instead you map `content` straight from the REST `content` | ||
| # field, the preview shows the raw wiki source — still safe | ||
| # (macro markup is inert text), just less polished. | ||
| endpoints: | ||
| # GET — list linked pages for an object | ||
| list: | ||
| method: GET | ||
| path: "" # relative to `location` | ||
| # The pairing store — which XWiki pages are linked to which OR | ||
| # object — lives in OpenConnector's own pairing model, keyed by | ||
| # the {register, schema, object} context. OpenConnector resolves | ||
| # the linked references, fetches each page's metadata from XWiki | ||
| # REST, and (for the preview) the rendered body from | ||
| # /bin/get/{Space}/{Page}?xpage=plain. | ||
| response: | ||
| rowsPath: "$" # bare array, or "$.results" | ||
| map: | ||
| reference: "id" # e.g. "xwiki:Sandbox.IntegrationTest" | ||
| title: "title" | ||
| space: "space" | ||
| page: "name" | ||
| url: "xwikiAbsoluteUrl" | ||
| breadcrumb: "hierarchy.items[*].label" # AD-3 — native XWiki breadcrumb | ||
| content: "renderedContent" # AD-1 — set from /bin/get/...?xpage=plain (see note above) | ||
|
|
||
| # GET {id} — one linked page (with rendered content for the preview) | ||
| get: | ||
| method: GET | ||
| path: "{id}" | ||
|
|
||
| # POST — link a page (body carries `reference`: a full XWiki URL | ||
| # or a `Space.Page` path; OpenConnector resolves both to canonical) | ||
| create: | ||
| method: POST | ||
| path: "" | ||
|
|
||
| # PUT {id} — update a pairing | ||
| update: | ||
| method: PUT | ||
| path: "{id}" | ||
|
|
||
| # DELETE {id} — unlink (removes the pairing; does NOT delete the | ||
| # page in XWiki) | ||
| delete: | ||
| method: DELETE | ||
| path: "{id}" | ||
|
|
||
| # Health probe used by OpenRegister's admin UI / OCS capabilities. | ||
| # A cheap authenticated GET that returns 200 when the instance is | ||
| # reachable and the credentials are valid. | ||
| healthCheck: | ||
| method: GET | ||
| path: "" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # XWiki Integration ("Articles") | ||
|
|
||
| Link XWiki pages to OpenRegister objects. Appears as the **Articles** tab in the object sidebar, as an `xwiki` widget on dashboards and detail pages, and as a single-entity reference renderer for schema properties that declare `referenceType: 'xwiki'`. | ||
|
|
||
| This is an **external** integration (storage strategy `external`, group `external`) — it is the worked example for the [pluggable integration registry](pluggable-integration-registry.md). It carries no HTTP client and no credentials of its own: all CRUD is delegated to an OpenConnector source named `xwiki`. | ||
|
|
||
| ## Setup | ||
|
|
||
| 1. **Install OpenConnector** (the `openconnector` Nextcloud app). The Articles integration is hidden until it's installed and enabled. | ||
| 2. **Create the `xwiki` source in OpenConnector** — import the template at [`xwiki-openconnector-source.yaml`](xwiki-openconnector-source.yaml), then fill in: | ||
| - `location` — your XWiki REST base URL, e.g. `https://wiki.example.org/rest/wikis/xwiki` | ||
| - the `auth` block — HTTP Basic (works on every XWiki version) **or** OAuth2 (xwiki-platform-oidc; newer instances). Keep exactly one. | ||
| 3. **Verify** in OpenRegister → Administration → OpenRegister → Integrations: the `xwiki` row should show storage `external`, required app `openconnector`, and an auth/health status. The "Configure" link deep-links into OpenConnector's source page; "Test connection" probes the source. | ||
|
|
||
| ## Using it | ||
|
|
||
| - **Sidebar (Articles tab)** — shows linked pages with their full breadcrumb ("Wiki / Department / Subspace / Page"), since two pages can share a title in different spaces. Link a page by pasting its **URL** (parsed to a canonical `Space.Page` reference) or by typing the **path** directly. Unlink removes the pairing only — it never deletes the page in XWiki. An "authentication expired" banner appears if the source's credentials need re-connecting. | ||
| - **Detail-page widget** — linked pages list plus a **text preview** (the first ~500 characters of the page's rendered content) and a link to the full page. **XWiki macros are not executed** in the preview (no Velocity templates / scripts run inside Nextcloud) — click through to XWiki for full rendering. | ||
| - **Dashboard widget** — recent linked pages (user dashboard) or app-scoped (app dashboard). | ||
| - **Reference property** — a schema property with `referenceType: 'xwiki'` renders the linked page's title + breadcrumb chip in `CnFormDialog` / `CnDetailGrid`. | ||
|
|
||
| ## Notes | ||
|
|
||
| - **Permissions** — the integration inherits access from the underlying object's RBAC plus OpenConnector's own. If a user has Nextcloud access to the object but not XWiki access to a page, they see a "No access to page" placeholder, not an internal error. | ||
| - **XWiki versions** — 5.x / 10.x+ / 14.x+ are all supported; the OpenConnector adapter normalises REST field-name drift, so the provider stays version-agnostic. | ||
| - **Failure modes** — if OpenConnector is missing/disabled, the source is missing, or the remote XWiki is down, the tab degrades to an empty state with a clear message rather than a broken tab (AD-23). | ||
|
|
||
| See [pluggable-integration-registry.md](pluggable-integration-registry.md) for how this integration is wired into the registry, and `openspec/changes/integration-xwiki/` for the change spec. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[CONCERN] XwikiProvider registered in bootBuiltinIntegrationProviders — misleading coupling for a leaf provider
bootBuiltinIntegrationProviders()is named for built-in providers that ship unconditionally. XwikiProvider is an external leaf that requires OpenConnector and a running XWiki. A separatebootLeafIntegrationProviders()or at minimum a descriptive comment block separating the sections would make the coupling explicit.