Skip to content

Repair account creation via CLI - #10726

Open
i2h3 wants to merge 1 commit into
masterfrom
i2h3/fix/cli-setup
Open

Repair account creation via CLI#10726
i2h3 wants to merge 1 commit into
masterfrom
i2h3/fix/cli-setup

Conversation

@i2h3

@i2h3 i2h3 commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Problem

Nextcloud --userid=admin --apppassword=admin --serverurl=http://… printed Unrecognized option '--userid=admin'. Fixing that spelling only exposed the next failure, and so on — account setup from the command line could not succeed on macOS at all.

Defects fixed

# Defect
1 Only --option value was parsed, never --option=value
2 --localdirpath documented optional, but an empty one was rejected
3 FolderMan::addFolder() refuses classic folders in File Provider mode; setup always created one
4 09f46929e3 added the account and folder before authenticating, and quit before the credential check, save and keychain write could run

Also: the failure path called deleteAccount(), revoking the app password passed on the command line, and cfg.setVfsEnabled() ran on every start, clobbering the user's setting.

Notes

nextcloudcmd needs an event loop for the now fully asynchronous setup. Its QtKeychain jobs never emit finished — pre-existing, hidden by the previous immediate return. The wait is bounded at 30 s so provisioning terminates with a warning rather than hanging; whether the signed release binary is affected is still open.

Testing

Against a local server, with the built client:

  • --userid=… inline form accepted; account created, dav_user set, password in keychain
  • no --apppassword: account created
  • classic sync mode without --localdirpath: default folder derived and created
  • wrong password: exits 1 with an error and leaves no account behind
  • --userid=: reports userid not specified
  • all scenarios from testnextcloudcmdprovisioning behave as the test expects

Setting up an account with --userid/--apppassword/--serverurl never
succeeded on macOS. Four independent defects were involved:

- Options were only accepted as "--option value". Argument lists are now
  normalised with Utility::expandCommandLineOptionValues(), so the
  "--option=value" spelling works for every option in both the client and
  nextcloudcmd. The latter has to normalise before it checks for --userid,
  which is what selects provisioning mode.

- --localdirpath is documented as optional but an empty one was rejected
  outright, although the setup already had a branch for accounts without a
  folder. It now falls back to the folder the account wizard would suggest.

- FolderMan::addFolder() refuses to create a classic sync folder while the
  app-level File Provider mode is enabled, yet the setup always tried to
  create one, so it always failed. localSyncFolderRequired() now mirrors
  that guard and the account is set up without a folder in that mode.

- 09f4692 added the account and its sync folder before the credentials
  were checked. Setting up the folder ends by scheduling qApp->quit(), so
  the credential check, the account save and the keychain write never ran.
  The account is now only added once the credentials validate, which also
  means a failed setup no longer leaves a half-written account behind.

Two related fixes: a failed folder setup called deleteAccount(), revoking
the app password that was passed on the command line, and the client
overwrote the configured VFS setting on every start because the account
setup parser instance is never null.

nextcloudcmd now runs the event loop so the asynchronous setup can finish.
Its keychain jobs never signal completion, which the previous immediate
return hid; the wait for the credentials is bounded so provisioning ends
with a warning instead of hanging.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@i2h3 i2h3 added this to the 34.0.4 milestone Sep 2, 2026
@i2h3
i2h3 requested a balanced review from Copilot September 2, 2026 17:14
@i2h3 i2h3 self-assigned this Sep 2, 2026
@github-project-automation github-project-automation Bot moved this to 🧭 Planning evaluation (don't pick) in 💻 Desktop Clients team Sep 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Provisioning still has malformed-option, File Provider initialization, credential persistence, and test-coverage issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Repairs command-line account provisioning and asynchronous credential persistence.

Changes:

  • Supports --option=value syntax.
  • Defers account creation until authentication succeeds.
  • Handles default folders, File Provider mode, cleanup, and keychain timeouts.
File summaries
File Description
src/gui/application.cpp Normalizes options and protects VFS settings.
src/gui/accountsetupfromcommandlinejob.h Declares folder-selection helpers.
src/gui/accountsetupfromcommandlinejob.cpp Reworks provisioning lifecycle and persistence.
src/common/utility.h Declares argument normalization utility.
src/common/utility.cpp Implements inline-option expansion.
src/cmd/cmd.cpp Adds normalization and asynchronous event loop.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 6
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/cmd/cmd.cpp

auto args(app_args);
// Accept both "--option value" and "--option=value" for every option below.
auto args = Utility::expandCommandLineOptionValues(app_args);
Comment on lines +57 to +61
#ifdef BUILD_FILE_PROVIDER_MODULE
// Mirrors the guard in FolderMan::addFolder(): while the app-level File Provider mode
// is enabled, a classic sync folder cannot be created at all. The account is synced
// through the File Provider domain that is set up for it instead.
return !ConfigFile().macFileProviderModeEnabled();

credentialsPersistTimer->start(credentialsPersistTimeout);

accountManager->save();
Comment thread src/common/utility.cpp
return noLeadingSlashPath(noTrailingSlashPath(relativePathToRemoteSyncRoot));
}

QStringList Utility::expandCommandLineOptionValues(const QStringList &arguments)
#include "theme.h"

#include <chrono>
#include <iostream>
finishAccountSetup();
});

credentialsPersistTimer->start(credentialsPersistTimeout);
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Artifact containing the AppImage: nextcloud-appimage-pr-10726.zip

Digest: sha256:3de7d746fe2a5c26f96c10cd989c85b5e43b0faa40234b2e0a9e719aeea261ac

To test this change/fix you can download the above artifact file, unzip it, and run it.

Please make sure to quit your existing Nextcloud app and backup your data.

@sonarqubecloud

sonarqubecloud Bot commented Sep 2, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
14.3% Coverage on New Code (required ≥ 80%)
8 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@i2h3 i2h3 moved this from 🧭 Planning evaluation (don't pick) to 📄 To do in 💻 Desktop Clients team Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 📄 To do

Development

Successfully merging this pull request may close these issues.

2 participants