Unsolved problems
ONLYOFFICE problems
Save button, dirty state, & drafts
ONLYOFFICE’s Document Editor API does not provide any method to programmatically mark a document as “dirty” (modified) or to force-enable its native Save button. The Save button remains disabled and does not trigger any callback (status 6) unless the user has made an actual manual edit to the document content first. This creates a problem for workflows involving unsaved drafts, where the document loads with existing unsaved changes that the editor cannot detect. The editor stores its dirty state internally with no public getter or setter. To work around this, we can either patch onlyoffice or hide the native Save button using CSS injection after the editor loads (targeting classes like btn-save or id-toolbar-btn-save) and replace it with a custom button (in main window, not iframe?). The custom button would call docEditor.downloadAs(“docx”) to fetch the current document state as a blob, then save that blob as a new file version. To handle the Ctrl+S keyboard shortcut, we would need to add a global keydown event listener on the window that intercepts the key combination, prevents its default behavior (to avoid triggering the native browser save dialog), and then manually calls the custom save function. The docEditor is in a separate iframe, complicating the communication between the main app and the onlyoffice editor.
previews and workspace_id
File previews need to have workspace_id set on the blob record of the preview. There is not an easy way to do it.
One way might be to override the attach method in active_storage/attached/one.rb:
def attach(attachable)
record.public_send("#{name}=", attachable)
if record.persisted? && !record.changed?
return if !record.save
end
record.public_send("#{name}")
end
Currently, we solve this by setting the workspace id of previews in the blob controller as we are serving previews. It updates the variant record if workspace_id is empty but the parent blob has workspace_id set.
Username not encrypted
This is not currently possible:
module People
class Membership < ApplicationRecord
raft_encrypts :username, deterministic: true
end
end
Why?
- We require username to authenticate.
- Once the username is specified, we know the list of potential credentials and their PRF salts.
There two ways to fix this:
- Create a separate username for authentication that is not the same as the username displayed in the app.
- We could encrypt membership.username, and then use universal salt for all PRF (instead of a per-credential salt).
Column encryption doesn’t have access to the record
It would be very useful if the code that handled column encryption had access to the full record and not just the value for the column.
For example, then the correct key could be automatically loaded from the vault.
However, currently, the way Raft implements column encryption is to use subclass ActiveModel::Type::Value which does not have access to the record. This is how Rails built-in column encryption works, and it has a lot of benefits in the way it smoothly integrates with Rails and ActiveRecord queries.