Skip to content

Add native ONLYOFFICE editing support for DMSF documents (BETA) - #37

Draft
p4535992 wants to merge 15 commits into
picman:onlyofficefrom
p4535992:feature/onlyoffice-dmsf-integration
Draft

p4535992 wants to merge 15 commits into
picman:onlyofficefrom
p4535992:feature/onlyoffice-dmsf-integration

Conversation

@p4535992

@p4535992 p4535992 commented Aug 3, 2026 •

Copy link
Copy Markdown

Summary

Beta status: This PR is a ready to test development version. It should be ready for developmen use. I am sharing it in case the implementation and overall approach may be useful for testing or further development on your side. Any feedback on whether the concept fits the DMSF architecture would be greatly appreciated.

This PR adds native ONLYOFFICE Docs integration to DMSF, allowing users to view and edit supported office documents directly from the DMSF interface.

The integration is designed specifically for the DMSF revision model. Unlike standard Redmine attachments, DMSF documents are not overwritten when they are updated. Every successful ONLYOFFICE editing session creates a new DmsfFileRevision.

This addresses the limitation described in:

  • https://github.com/danmunn/redmine_dmsf/issues/1334
  • https://github.com/ONLYOFFICE/onlyoffice-redmine

Motivation

The official ONLYOFFICE Redmine plugin works with Redmine Attachment records and replaces the underlying attachment content after editing.

DMSF uses a different storage and versioning model:

  • documents are represented by DmsfFile;
  • document versions are represented by DmsfFileRevision;
  • each update must create a new revision;
  • revision metadata, permissions, locks, notifications, and approval workflows must be handled by DMSF.

For this reason, directly reusing the standard attachment callback would overwrite document content and bypass DMSF revision management.

This implementation integrates ONLYOFFICE directly with DMSF while remaining compatible with an existing ONLYOFFICE Document Server.

Main features

  • Open supported DMSF documents in ONLYOFFICE Viewer.
  • Edit supported DMSF documents in ONLYOFFICE Editor.
  • Create a new DMSF revision after a successful editing session.
  • Preserve the original revision instead of overwriting it.
  • Copy custom-field values to the newly created revision.
  • Associate the new revision with the user who started the editing session.
  • Reuse settings from the official onlyoffice_redmine plugin when available.
  • Support standalone DMSF-specific ONLYOFFICE configuration.
  • Support public and internal URLs for Docker, private networks, and reverse proxies.
  • Support JWT authentication using HS256, HS384, and HS512.
  • Protect download and callback endpoints with signed URLs.
  • Validate permissions and document locks when the editor is opened and again when the callback is received.
  • Prevent duplicate callback processing.
  • Reject stale saves when a newer DMSF revision already exists.
  • Enforce the Redmine maximum attachment size.
  • Reset the DMSF approval workflow for newly created revisions.
  • Trigger the standard DMSF notification flow after a revision is created.

User interface

Two new actions are available for supported documents:

  • View in ONLYOFFICE
  • Edit in ONLYOFFICE

The edit action is shown only when the current user has permission to modify the document and the file is not locked by another user.

View sessions use a revision-specific editor key.

Edit sessions use a shared revision key so multiple users can collaborate on the same current revision.

Save and revision behavior

When ONLYOFFICE reports that a document is ready to be saved:

  1. The callback JWT and signed request parameters are validated.
  2. The DMSF file and source revision are loaded.
  3. User permissions and file-lock status are checked again.
  4. The callback is rejected when the source revision is no longer the latest revision.
  5. The edited file is downloaded from the ONLYOFFICE Document Server.
  6. The file size and download origin are validated.
  7. A new DmsfFileRevision is created.
  8. Metadata and custom fields are copied from the source revision.
  9. The revision number is incremented according to the configured version-bump strategy.
  10. DMSF notifications are triggered.

The source revision is never overwritten.

ONLYOFFICE callback status 2 creates the new DMSF revision.

Force-save callback status 6 is acknowledged but does not create a revision, preventing automatic background saves from generating unnecessary DMSF versions.

Conflict handling

The editor configuration includes the ID of the revision used to start the session.

Before saving, the callback verifies that this revision is still the latest revision of the DMSF file.

When another revision has already been created, the callback is rejected instead of silently overwriting or superseding newer work.

Duplicate callback requests are also detected so that repeated ONLYOFFICE notifications do not create multiple identical revisions.

Security

The integration includes:

  • JWT signing for the ONLYOFFICE editor configuration;
  • JWT verification for Document Server callbacks;
  • support for JWT tokens received in the request body or authorization header;
  • signed document-download URLs;
  • signed callback URLs;
  • constant-time signature comparison;
  • configurable JWT algorithms;
  • download-host validation;
  • maximum file-size validation;
  • permission validation at editor-open time;
  • permission validation at callback time;
  • lock validation at callback time;
  • CSRF exemption limited to the Document Server callback endpoint.

The JWT secret must match the secret configured on the ONLYOFFICE Document Server.

Configuration

The integration can work in two modes.

Reuse the official ONLYOFFICE plugin settings

When onlyoffice_redmine is installed, DMSF can reuse its configuration, including:

  • public Document Server URL;
  • internal Document Server URL;
  • internal Redmine URL;
  • JWT secret;
  • JWT algorithm;
  • JWT header;
  • SSL verification settings.

This allows the standard Redmine integration and DMSF integration to use the same Document Server.

Standalone DMSF configuration

DMSF can also be configured independently with:

  • ONLYOFFICE Document Server public URL;
  • ONLYOFFICE Document Server internal URL;
  • Redmine internal URL;
  • JWT secret;
  • JWT algorithm;
  • JWT header;
  • SSL certificate verification;
  • supported editable extensions;
  • revision version-bump strategy.

Network and reverse-proxy support

Separate public and internal URLs are supported.

This is useful when:

  • users access Redmine through a public HTTPS address;
  • the Document Server accesses Redmine through a Docker service name;
  • Redmine accesses ONLYOFFICE through an internal network;
  • Redmine is installed below a reverse-proxy subpath;
  • public and private DNS names are different.

URLs included in the editor configuration are rewritten to use the appropriate public or internal endpoint depending on which service consumes them.

Supported formats

The integration is enabled only for configured office-document extensions supported by the connected ONLYOFFICE Document Server.

Unsupported files continue to use the standard DMSF download and preview behavior.

LibreOffice compatibility

This integration does not remove the existing LibreOffice-based preview functionality.

ONLYOFFICE is added as an alternative for online document viewing and editing.

Administrators who no longer need LibreOffice-generated previews may leave the DMSF office_bin setting empty.

Backward compatibility

  • Existing DMSF documents and revisions are unchanged.
  • Existing download, preview, WebDAV, and revision-management flows remain available.
  • The integration is disabled by default until a Document Server is configured.
  • The official onlyoffice_redmine plugin is optional.
  • No existing DMSF revision is modified during installation.

Validation performed

The following checks were performed:

  • Ruby syntax validation.
  • YAML parsing.
  • ERB template compilation.
  • JWT encoding and decoding with HS256, HS384, and HS512.
  • JWT callback extraction from request bodies and headers.
  • Public/internal URL rewriting.
  • Reverse-proxy subpath handling.
  • Patch applicability.
  • ZIP archive integrity.

Deployment notes

After installing the updated plugin, run:

RAILS_ENV=production bundle exec rake redmine:plugins:migrate NAME=redmine_dmsf

Then restart Redmine and configure ONLYOFFICE under:

Administration → Plugins → DMSF → Configure

The Redmine URL used by the Document Server must be reachable from the Document Server container or host.

The Document Server URL configured in Redmine must also be reachable from the Redmine container or host.

Related issues

Closes or addresses:

  • https://github.com/danmunn/redmine_dmsf/issues/1334

Introduce ONLYOFFICE Document Server integration allowing supported DMSF files to be opened for viewing and collaborative editing via the existing server, with callbacks persisting edited content as new DMSF revisions instead of overwriting attachments.

- Expose configurable Document Server URLs, JWT settings, and reuse of the official plugin's settings
- Add view/edit controls in the file show view and context menu when the file type is supported
- Filter force-save callbacks to avoid creating revisions on each automatic save and reject callbacks when newer revisions exist
- Document the new plugin settings, migration step, and callback behavior in the README
@picman
picman changed the base branch from master to devel August 7, 2026 14:06
@picman
picman self-requested a review August 7, 2026 14:06
@picman picman added the enhancement New feature or request label Aug 10, 2026
@picman picman added this to the 5.1.1 milestone Aug 10, 2026
@picman

picman commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Some test don't pass. Please fix it. Also don't forget to check your code using Rubocop prior committing.

@p4535992

Copy link
Copy Markdown
Author

I'll close for now

@p4535992 p4535992 closed this Aug 10, 2026
@p4535992 p4535992 reopened this Aug 10, 2026
@picman

picman commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Run locally:

cd redmine
bundle exec rake redmine:plugins:test:units NAME=redmine_dmsf RAILS_ENV=test
bundle exec rake redmine:plugins:test:functionals NAME=redmine_dmsf RAILS_ENV=test
bundle exec rubocop -c plugins/redmine_dmsf/.rubocop.yml plugins/redmine_dmsf/

If it passes, push your commits.

@p4535992
p4535992 marked this pull request as draft August 11, 2026 16:15
@picman

picman commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Any progress? Can I help somehow?

@p4535992

Copy link
Copy Markdown
Author

It's just that I'm not that familiar with Rail and Redmine XD, i need to put some more effort on it.

I'll try to get back to it as soon as I can.

@picman picman modified the milestones: 5.1.1, 5.1.2 Aug 19, 2026

@picman picman left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add all the new localized strings into all available languages, not only 'en' and 'it', in English to know which strings need to be translated.

@picman
picman changed the base branch from devel to onlyoffice August 20, 2026 07:10
- Add missing English strings to all locales, preserving translations
- Add localization regression tests and Rails functional tests
- Exempt signed Document Server endpoints from browser login checks
- Ensure User.current is restored after callback processing
- Normalize Ruby line endings and update test workflow triggers

Standalone localization tests and Ruby syntax checks passed.

Full Redmine unit and functional suites, RuboCop, and multi-version
testing remain pending. These changes have NOT been validated in a
complete Redmine environment or with a real ONLYOFFICE Document Server.
@p4535992

Copy link
Copy Markdown
Author

Thanks for the feedback. I have prepared the localization update and additional regression tests.

Important: I have not been able to validate these changes in a complete, running Redmine environment or with a real ONLYOFFICE Document Server. The requested Rails test suites and RuboCop have not been run, and multi-version compatibility has not been verified.

1. Localization

All 29 new ONLYOFFICE localization keys are now present in all 17 locale files.

For the 15 languages that were missing these entries, I added the English values and marked them for translation. The existing English and Italian entries, as well as all pre-existing translations, have been preserved.

A standalone localization regression test was also added to check key coverage, non-empty values, interpolation consistency, and duplicate keys without relying on translation fallbacks.

2. Limited checks completed

The following checks were completed on the prepared update:

  • Standalone localization tests: 4 tests, 2,528 assertions, 0 failures, 0 errors.
  • Ruby syntax validation: 252 source files passed.

These are limited checks only. They do not verify Rails integration, database behavior, HTTP requests, or document editing and saving through ONLYOFFICE.

I also added 18 Rails functional tests, but these have not yet been executed in a complete Redmine environment.

3. Required validation still pending

The following commands still need to be run from the Redmine root directory:

bundle exec rake redmine:plugins:test:units NAME=redmine_dmsf RAILS_ENV=test
bundle exec rake redmine:plugins:test:functionals NAME=redmine_dmsf RAILS_ENV=test
bundle exec rubocop -c plugins/redmine_dmsf/.rubocop.yml plugins/redmine_dmsf/

Testing across the applicable supported Redmine versions and an end-to-end check with a real ONLYOFFICE Document Server are also still pending.

The localization request is addressed in the prepared changes, but the testing request remains open. I am not claiming that the full test suites pass or that the integration is ready for production.

@p4535992

Copy link
Copy Markdown
Author

Hi, thanks for taking a look at this.

I’ve done some work on the implementation, but I’m not experienced enough with the project to clearly understand the best way to integrate it into the existing codebase.

Would you be willing to use my work as a starting point and handle the actual integration yourself?

I’d be happy if what I’ve already done could at least serve as a base or reference, and of course I can help clarify anything about my changes if needed.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants