From ff46aad6159e3de24f815a5eea35aad1b2c01dbc Mon Sep 17 00:00:00 2001 From: Andriy Oblivantsev Date: Tue, 22 Sep 2026 22:41:58 +0100 Subject: [PATCH] chore: keep the re-landed feature files showroom-safe The conversion / link / sheet commits predate the tree cleanup, so their comments and README/test examples still carried internal refs. Re-apply the genericization (no internal hosts, personal names or client file ids). --- README.md | 42 +++++++++++++++++++++++----------------- auth.go | 8 ++++---- cmd/oo/docs.go | 4 ++-- cmd/oo/link.go | 9 ++++----- cmd/oo/projects_files.go | 5 ++--- cmd/oo/users.go | 8 ++++---- convert.go | 2 +- links.go | 17 ++++++++-------- links_test.go | 2 +- sheets_test.go | 6 +++--- 10 files changed, 53 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 5e78088..7c6a12b 100644 --- a/README.md +++ b/README.md @@ -557,7 +557,7 @@ Example — convert a portal file (or a local file) to PDF with the native engin ```bash export ONLYOFFICE_DS_SECRET= -oo docs pdf 3684 --out out.pdf # OO file id → PDF +oo docs pdf 1234 --out out.pdf # OO file id → PDF oo docs pdf ./report.docx --to pdf # local file → PDF (temp upload, auto-cleanup) ``` @@ -619,35 +619,35 @@ oo cases list oo crm-tasks categories # Deep links & native document conversion -oo link 3684 3694 # DocEditor URL for file ids (title + url) -oo docs presigned 3684 # short-lived fetchable URL of an OO file -oo docs pdf 3684 --out out.pdf # OO file → PDF (via DocumentServer) +oo link 1234 2345 # DocEditor URL for file ids (title + url) +oo docs presigned 1234 # short-lived fetchable URL of an OO file +oo docs pdf 1234 --out out.pdf # OO file → PDF (via DocumentServer) oo docs pdf ./report.docx --to pdf # local file → PDF on the fly (temp upload+cleanup) -oo docs pdf 3684 --stream > out.pdf # pipe: bytes to stdout (alias --pipe) +oo docs pdf 1234 --stream > out.pdf # pipe: bytes to stdout (alias --pipe) # Spreadsheet export (sheet-aware; local reader — the DS csv output is first-sheet-only) -oo docs csv 227 --sheet 2 # XLS/XLSX/ODS worksheet → CSV (--sheet N, 1-based) -oo docs csv 227 --delimiter ';' # ; | | \t via --delimiter -oo docs json 227 --sheet 2 # worksheet → JSON rows (first row = header) +oo docs csv 1234 --sheet 2 # XLS/XLSX/ODS worksheet → CSV (--sheet N, 1-based) +oo docs csv 1234 --delimiter ';' # ; | | \t via --delimiter +oo docs json 1234 --sheet 2 # worksheet → JSON rows (first row = header) oo docs csv ./book.xlsx --sheet 1 --out sheet1.csv # export ONLYOFFICE_DS_SECRET= # docs base: $ONLYOFFICE_DOCS_URL, else $ONLYOFFICE_URL + /ds-vpath # Project team (portal users) CRUD -oo projects team list 219 -oo projects team add 219 [...] -oo projects team remove 219 -oo projects team set 219 [...] # replace team (may lag; verify with list) -oo projects milestone-delete 38 +oo projects team list 42 +oo projects team add 42 [...] +oo projects team remove 42 +oo projects team set 42 [...] # replace team (may lag; verify with list) +oo projects milestone-delete 7 # Project documents: fresh re-upload (single clean version) / new version -oo projects files replace-in 495 ./contract.pdf # hard delete same stem|ext in folder + upload -oo projects files update 3647 ./contract.docx # overwrite content, same file id +oo projects files replace-in 1 ./contract.pdf # hard delete same stem|ext in folder + upload +oo projects files update 1 ./contract.docx # overwrite content, same file id # Users lifecycle oo users list ; oo users get -oo users create --first Morgane --last Avéus --email morgane@example.com --password '…' -oo users check --login morgane@example.com # verify login (email works when userName 500s) +oo users create --first Jane --last Doe --email jane.doe@example.com --password '…' +oo users check --login jane.doe@example.com # verify login (email works when userName 500s) oo users update --title "…" --location "…" oo users block ; oo users unblock oo users password # reads the new password from stdin @@ -835,7 +835,7 @@ kontolink IN.xlsx oo-index.tsv OUT.xlsx [FILE_ID] [AMOUNTS_TSV] | `mails` | `accounts`, `folders`, `list`, `get`, `download-attachment`, `draft`, `attach`, `draft-invoice`, `send`, `delete` | | `cases` | `list`, `create`, `delete`, `member-add` | | `crm-tasks` | `list`, `create`, `delete`, `categories`, `reassign-self` | -| `docs` | `tools`, `convert`, `optimize`, `ocr`, `hocr`, `as-md`, `put-md`, `put-txt`, `put-xlsx` | +| `docs` | `tools`, `convert`, `pdf`, `presigned`, `csv`, `json`, `optimize`, `ocr`, `hocr`, `as-md`, `put-md`, `put-txt`, `put-xlsx` | | `catalog` | `match`, `merge`, `apply`, `scan-contacts`, `scan-projects`, `scan-thunderbird` | | `dav` | `ls`, `move`, `copy`, `mkdir`, `rename-file`, `rename-folder`, `download`, `fileops` | | `search` | `QUERY` (`--content`, `--folder ID`, `--limit N`, `--backend oo\|own`, `--json`) | @@ -847,6 +847,12 @@ CLI-only concern — the library itself never loads dotfiles). Canonical `ONLYOFFICE_*` variables win over aliases. Optional CLI-only aliases: `OO_URL` / `OO_USER` / `OO_PASS` → `ONLYOFFICE_URL` / `ONLYOFFICE_USER` / `ONLYOFFICE_PASS`. +Catalog scanning (`oo catalog scan-projects` / `scan-thunderbird`) classifies +clients from rules in `$OO_CATALOG_CONFIG` (or `--config`); see +[`catalog/classify.example.yaml`](catalog/classify.example.yaml). Without rules +nothing is classified as work. The MinIO download fallback is off unless +`MINIO_ENDPOINT` + `MINIO_ACCESS_KEY` + `MINIO_SECRET_KEY` are set. + Run `oo --help` or `oo --help` for the full command reference. > **0.5.0 migration note:** the command tree was flattened per-subject. Old diff --git a/auth.go b/auth.go index 5a11348..22b4c65 100644 --- a/auth.go +++ b/auth.go @@ -103,10 +103,10 @@ func (c *Client) authenticateOnce(ctx context.Context) error { // token, and the portal error otherwise. // // OnlyOffice accepts either the userName or the account email as the login. On -// the arc-1 portal (office.produktor.io) the account userName login returns -// HTTP 500 "User authentication failed" while the account email succeeds — -// confirmed for a freshly created guest user. Use this probe before sharing -// credentials (see `oo users check`), and prefer the email as the login. +// some portals the account userName login returns HTTP 500 "User authentication +// failed" while the account email succeeds — confirmed for a freshly created +// guest user. Use this probe before sharing credentials (see `oo users check`), +// and prefer the email as the login. func (c *Client) AuthenticateAs(ctx context.Context, login, password string) error { body, err := json.Marshal(Credentials{User: login, Password: password}) if err != nil { diff --git a/cmd/oo/docs.go b/cmd/oo/docs.go index 1f206c5..9cac059 100644 --- a/cmd/oo/docs.go +++ b/cmd/oo/docs.go @@ -87,7 +87,7 @@ uploaded to the scratch folder (--folder, default 2 = "My documents"), converted downloaded and then removed — so any local document yields a PDF on the fly. Docs base defaults to $ONLYOFFICE_DOCS_URL, else $ONLYOFFICE_URL + "/ds-vpath" -(the portal nginx proxies /ds-vpath to the DocumentServer). The JWT secret is +(/ds-vpath is the usual reverse-proxy mount for the DocumentServer). The JWT secret is $ONLYOFFICE_DS_SECRET (DocumentServer services.CoAuthoring.secret).`, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -334,7 +334,7 @@ Each data row becomes an object keyed by the header cells of that sheet.`, } // docsBaseURL resolves the DocumentServer base: --docs-url, $ONLYOFFICE_DOCS_URL, -// else the portal's /ds-vpath proxy. +// else the standard /ds-vpath reverse-proxy mount. func docsBaseURL(flag string) string { if flag != "" { return flag diff --git a/cmd/oo/link.go b/cmd/oo/link.go index 34a8eae..df1cea4 100644 --- a/cmd/oo/link.go +++ b/cmd/oo/link.go @@ -9,11 +9,10 @@ func init() { rootCmd.AddCommand(linkCmd()) } -// linkCmd prints deep links for file ids. Used to build the third-party -// document packs (e.g. the arc-1 "Lisbon apartment" Info cover embeds links to -// passports, contracts and the income documents). File ids come from -// `oo projects files list` / `oo dav ls`; `oo projects files replace-in` keeps -// them clean when a document is re-uploaded. +// linkCmd prints deep links for file ids. Used to build third-party document +// packs whose cover embeds links to contracts and supporting files. File ids +// come from `oo projects files list` / `oo dav ls`; `oo projects files +// replace-in` keeps them clean when a document is re-uploaded. func linkCmd() *cobra.Command { return &cobra.Command{ Use: "link FILE_ID [FILE_ID...]", diff --git a/cmd/oo/projects_files.go b/cmd/oo/projects_files.go index 9b63d71..e44912e 100644 --- a/cmd/oo/projects_files.go +++ b/cmd/oo/projects_files.go @@ -159,9 +159,8 @@ func prjFilesReplaceInCmd() *cobra.Command { delete is permanent) and uploads the local file fresh. Unlike 'update' this leaves a single clean version. -Why it exists: on the arc-1 portal, repeated 'update' of a shared document -(the apartment "Info" cover and the Edelweiss contract) accumulated a visible -version history and a stale id. replace-in yields one clean revision; then +Why it exists: repeated 'update' of a shared document accumulated a visible +version history and left a stale id. replace-in yields one clean revision; then point links at the returned id (or keep an nginx alias for the legacy fileid). Note: file ids are server-assigned; a fresh upload gets a new id.`, diff --git a/cmd/oo/users.go b/cmd/oo/users.go index 5fafe58..2fe4f10 100644 --- a/cmd/oo/users.go +++ b/cmd/oo/users.go @@ -322,10 +322,10 @@ func usersCheckCmd() *cobra.Command { discards the token. Where this is used: before handing portal credentials to an external party -(e.g. a landlord given read access to the apartment document pack), verify the -login actually works. On the arc-1 portal the account email is the reliable -login identifier — the userName login fails with 500 for a freshly created -user, so share the email, not the userName.`, +(e.g. a guest given read access to a document pack), verify the login actually +works. On some portals the account email is the reliable login identifier — the +userName login fails with 500 for a freshly created user — so share the email, +not the userName.`, RunE: func(cmd *cobra.Command, args []string) error { if login == "" { return fmt.Errorf("--login is required (userName or email)") diff --git a/convert.go b/convert.go index 04b953f..40c294c 100644 --- a/convert.go +++ b/convert.go @@ -4,7 +4,7 @@ package onlyoffice // // The DocumentServer (the same engine behind the portal's "Download as PDF") // converts any office format. From a portal-reachable host the converter is -// exposed at "/ds-vpath/converter" (nginx proxy) or directly at +// exposed at "/ds-vpath/converter" (reverse proxy) or directly at // "http://:8083/converter" (legacy path: /ConvertService.ashx). // // Flow: PresignedURI(fileId) → Convert(docsBase, secret, req) → download diff --git a/links.go b/links.go index 3439608..81be6c7 100644 --- a/links.go +++ b/links.go @@ -2,16 +2,15 @@ package onlyoffice // Deep links to OnlyOffice portal objects. // -// Where this is used: third-party-facing document packs (e.g. the arc-1 -// office.produktor.io "Lisbon apartment" project) embed per-file links of the -// form /Products/Files/DocEditor.aspx?fileid= in a cover document and in -// chat messages. Those links must be generated consistently so they match the -// file ids returned by `oo projects files list` / `oo link`. +// Used by tools that embed per-file links of the form +// /Products/Files/DocEditor.aspx?fileid= in a cover document or a chat +// message. Those links must be consistent so they match the file ids returned +// by `oo projects files list` / `oo link`. // -// Caveat proven on the arc-1 portal: file ids are server-assigned and a -// re-upload/delete yields a NEW id, so an already-shared link can go stale. -// Use `oo projects files replace-in` (keep the id clean) and, if a legacy link -// must keep working, an nginx alias can 302 the old fileid to the new one. +// Caveat: file ids are server-assigned and a re-upload/delete yields a NEW id, +// so an already-shared link can go stale. Use `oo projects files replace-in` +// (keeps the id stable) and, if a legacy link must keep working, an nginx alias +// can 302 the old fileid to the new one. import ( "fmt" diff --git a/links_test.go b/links_test.go index e443e19..253cbc7 100644 --- a/links_test.go +++ b/links_test.go @@ -5,7 +5,7 @@ import "testing" func TestFileEditorURL(t *testing.T) { cases := []struct{ base, id, want string }{ {"https://office.example.com", "3651", "https://office.example.com/Products/Files/DocEditor.aspx?fileid=3651"}, - {"https://office.example.com/", " 3687 ", "https://office.example.com/Products/Files/DocEditor.aspx?fileid=3687"}, + {"https://office.example.com/", " 1234 ", "https://office.example.com/Products/Files/DocEditor.aspx?fileid=1234"}, {"http://localhost:8087", "a/b", "http://localhost:8087/Products/Files/DocEditor.aspx?fileid=a%2Fb"}, } for _, c := range cases { diff --git a/sheets_test.go b/sheets_test.go index feee720..9f54319 100644 --- a/sheets_test.go +++ b/sheets_test.go @@ -17,7 +17,7 @@ func TestWorkbookSheetExport(t *testing.T) { _ = f.SetCellValue("first", "B2", 30) _, _ = f.NewSheet("second") _ = f.SetCellValue("second", "A1", "city") - _ = f.SetCellValue("second", "A2", "Lisbon") + _ = f.SetCellValue("second", "A2", "Berlin") var buf bytes.Buffer if err := f.Write(&buf); err != nil { t.Fatal(err) @@ -34,7 +34,7 @@ func TestWorkbookSheetExport(t *testing.T) { t.Fatalf("sheet0 csv=%q err=%v", csv0, err) } csv1, err := WorkbookSheetCSV(data, 1, 0) - if err != nil || !strings.Contains(csv1, "Lisbon") || strings.Contains(csv1, "Alice") { + if err != nil || !strings.Contains(csv1, "Berlin") || strings.Contains(csv1, "Alice") { t.Fatalf("sheet1 csv=%q err=%v", csv1, err) } // negative index = first sheet @@ -44,7 +44,7 @@ func TestWorkbookSheetExport(t *testing.T) { } js, err := WorkbookSheetJSON(data, 1) - if err != nil || len(js) != 1 || js[0]["city"] != "Lisbon" { + if err != nil || len(js) != 1 || js[0]["city"] != "Berlin" { t.Fatalf("sheet1 json=%#v err=%v", js, err) }