Skip to content

fix(files_sharing): restore password guard early return scoped to public shares only#59759

Closed
Copilot wants to merge 16 commits intomasterfrom
copilot/fix-save-twice-bug-public-shares
Closed

fix(files_sharing): restore password guard early return scoped to public shares only#59759
Copilot wants to merge 16 commits intomasterfrom
copilot/fix-save-twice-bug-public-shares

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

PR #59262 removed the return from the saveShare() password validation guard to fix a regression (#59254) where non-public shares were incorrectly blocked. That fix was too broad — removing return entirely re-introduced the original "save twice" bug for public shares: passwordError would be set but execution continued, incomingShare.password = undefined, and the share was created without the password.

Changes

  • apps/files_sharing/src/views/SharingDetailsTab.vue — add && this.isPublicShare to the guard condition and restore the return:
- if (this.isNewShare && !this.isValidShareAttribute(this.share.newPassword)) {
+ if (this.isPublicShare && this.isNewShare && !this.isValidShareAttribute(this.share.newPassword)) {
      this.passwordError = true
+     return
  }

Non-public shares never support passwords, so they should never be blocked by this guard. Public shares missing a required password are correctly blocked again.

  • apps/files_sharing/src/views/SharingDetailsTab.spec.ts — replaced tests that didn't account for isPublicShare with coverage for:

TODO

  • ...

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • download.cypress.io
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node dist/index.js --exec install /home/REDACTED/.cache/node-gyp/24.14.1/deps/zlib -I /home/REDACTED/.cache/node-gyp/24.14.1/deps/v8/include -I ../../../../../nan --64 -o Release/obj.target/sshcrypto/src/binding.o conf�� " "./Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/" --global tnet/tools/git copilot.originalas (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Problem

The "save twice" bug is back for public shares with a password. When a user creates a new public share and sets a password, the password is silently dropped on the first save — the share is created without the password — and the user must open the share settings and save a second time for the password to actually take effect.

Root cause

In apps/files_sharing/src/views/SharingDetailsTab.vue, inside saveShare(), there used to be a return guard that prevented saving when a new public share had isPasswordProtected enabled but share.newPassword was empty/invalid:

if (this.isPasswordProtected) {
    if (this.isNewShare && !this.isValidShareAttribute(this.share.newPassword)) {
        this.passwordError = true
        return  // ← was here
    }
} else {
    this.share.password = ''
}

PR #59262 removed the return to fix a regression introduced by PR #58226 where non-public shares (user/group shares) were incorrectly blocked from saving because isPasswordProtected was truthy for them too (due to passwordProtectedState state leaking). The fix was correct in intent but too broad — removing return entirely re-introduced the original "save twice" bug for public shares.

Without the return, on a new public share where newPassword is missing:

  1. passwordError = true is set and shown in the UI — but execution continues
  2. incomingShare.password = this.share.newPasswordundefined
  3. addShare()undefined is falsy → password is silently omitted from the createShare POST
  4. Share is created without a password
  5. User must save a second time for the password to apply

Fix

Scope the return guard to public shares only (isPublicShare). Non-public shares don't support passwords so they should never be blocked. Public shares that require a password should keep the hard block:

if (this.isPasswordProtected) {
    if (this.isPublicShare && this.isNewShare && !this.isValidShareAttribute(this.share.newPassword)) {
        this.passwordError = true
        return  // only block public shares missing a password
    }
} else {
    this.share.password = ''
}

This restores correct behaviour for public shares (block if password missing) while not regressing #59254 (non-public shares are no longer blocked since isPublicShare is checked first).

Files to change

  • apps/files_sharing/src/views/SharingDetailsTab.vue — add && this.isPublicShare to the existing isNewShare && !isValidShareAttribute(newPassword) guard and restore the return

Tests to add

Look for the existing test files for SharingDetailsTab.vue. They are likely in apps/files_sharing/src/views/__tests__/ or apps/files_sharing/src/tests/. Add test cases covering:

  1. New public share with password setsaveShare() should proceed (not return early), addShare should be called with the password
  2. New public share with password protection enabled but newPassword empty/undefinedsaveShare() should set passwordError = true and return early without calling addShare
  3. New non-public (user/group) sharesaveShare() should always proceed regardless of isPasswordProtected or newPassword state (regression test for [Bug]: Since NC 32.0.7 / 33.0.1 "Save share" Button without any function #59254)
  4. Existing public share (update path)saveShare() should call queueUpdate and not be blocked by the password guard (the guard only applies to isNewShare)

Use the existing test patterns and mocks already present in the test suite. Mock addShare, queueUpdate, createShare as needed.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: We've been having recurring issues with the sharing password sidebar on Server
@nextcloud/server/issues/57011
@nextcloud/server/pull/58226
@nextcloud/server/issues/59254
@nextcloud/server/pull/59267

Now after my last PR in 59262, it seems the save twice issue is back. Please check the PRs, commits and the edited file git history to understand the issues.
It used to work properly. Some users report 32.0.2 as latest working version.
Analyse this, find the root cause and offers a potential suggestion and explanation

Assistant: Now let me look at the current state of SharingDetailsTab.vue to understand the full saveShare flow:

Assistant: Now I have enough context to deliver a comprehensive analysis. Let me look at the critical saveShare method section.

Assistant: Let me now look at the saveShare method and ShareRequests.js to complete the picture:

Assistant: ## Root Cause Analysis

After tracing all the PRs and the current code, the root cause has been found. It's a pre-existing bug in addShare() that was never actually fixed, but got masked and then unmasked by the subsequent PRs.


The Core Bug — addShare() uses the wrong property

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

dependabot Bot and others added 4 commits April 20, 2026 20:49
Bumps the github-actions group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [dorny/paths-filter](https://github.com/dorny/paths-filter) | `3.0.2` | `4.0.1` |
| [actions/github-script](https://github.com/actions/github-script) | `8.0.0` | `9.0.0` |
| [github/codeql-action](https://github.com/github/codeql-action) | `4.35.1` | `4.35.2` |
| [actions/setup-node](https://github.com/actions/setup-node) | `6.3.0` | `6.4.0` |
| [andstor/file-existence-action](https://github.com/andstor/file-existence-action) | `3.0.0` | `3.1.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [LizardByte/actions](https://github.com/lizardbyte/actions) | `2026.328.161128` | `2026.417.35446` |
| [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) | `8.1.0` | `8.1.1` |


Updates `dorny/paths-filter` from 3.0.2 to 4.0.1
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](dorny/paths-filter@v3.0.2...fbd0ab8)

Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)

Updates `github/codeql-action` from 4.35.1 to 4.35.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@c10b806...95e58e9)

Updates `actions/setup-node` from 6.3.0 to 6.4.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@53b8394...48b55a0)

Updates `andstor/file-existence-action` from 3.0.0 to 3.1.0
- [Release notes](https://github.com/andstor/file-existence-action/releases)
- [Commits](andstor/file-existence-action@076e007...558493d)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@bbbca2d...043fb46)

Updates `LizardByte/actions` from 2026.328.161128 to 2026.417.35446
- [Release notes](https://github.com/lizardbyte/actions/releases)
- [Commits](LizardByte/actions@0affa4f...4125866)

Updates `peter-evans/create-pull-request` from 8.1.0 to 8.1.1
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](peter-evans/create-pull-request@c0f553f...5f6978f)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-version: 4.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/github-script
  dependency-version: 9.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 4.35.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-node
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: andstor/file-existence-action
  dependency-version: 3.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: LizardByte/actions
  dependency-version: 2026.417.35446
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: peter-evans/create-pull-request
  dependency-version: 8.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](juliangruber/brace-expansion@v2.0.2...v2.0.3)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 2.0.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
Copilot AI changed the title [WIP] Fix save twice bug for public shares with password fix(files_sharing): restore password guard early return scoped to public shares only Apr 21, 2026
Copilot AI requested a review from skjnldsv April 21, 2026 07:58
Copilot stopped work on behalf of skjnldsv due to an error April 21, 2026 07:59
@skjnldsv skjnldsv marked this pull request as ready for review April 21, 2026 08:13
@skjnldsv skjnldsv requested review from a team as code owners April 21, 2026 08:13
@skjnldsv skjnldsv requested review from nfebe and sorbaugh and removed request for a team April 21, 2026 08:13
come-nc and others added 11 commits April 21, 2026 10:21
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
…ctions

Register axios password confirmation interceptors in the apps
management, admin delegation, admin security, and OAuth2 settings
bundles, and pass PwdConfirmationMode.Strict on requests to endpoints
protected with #[PasswordConfirmationRequired(strict: true)], so that
the user password is verified via Basic auth on the request itself
rather than relying on the session timestamp.

Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
…ndling

fix: Reduce the mixups between apptokens and session ids
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
…thub-actions-d76c8db3f9

chore(deps): Bump the github-actions group with 8 updates
…d/frontend-legacy/brace-expansion-2.0.3

chore(deps): Bump brace-expansion from 2.0.2 to 2.0.3 in /build/frontend-legacy
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
…uired

fix: Add missing PasswordConfirmationRequired attributes
@skjnldsv skjnldsv force-pushed the copilot/fix-save-twice-bug-public-shares branch from 642bf4f to 9f061db Compare April 21, 2026 13:46
@skjnldsv
Copy link
Copy Markdown
Member

/compile

Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
@provokateurin provokateurin requested a review from susnux April 22, 2026 17:42
Copy link
Copy Markdown
Contributor

@susnux susnux left a comment

Choose a reason for hiding this comment

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

code change makes sense but did not test it.

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.

Those "tests" are a bit ridiculous (but not since this PR) testing your test code which (maybe) at some point is similar like the implementation 👀
Probably should rather be proper component tests or e2e tests.

@DorraJaouad DorraJaouad requested review from a team and provokateurin as code owners April 23, 2026 09:41
@DorraJaouad DorraJaouad requested review from ArtificialOwl and salmart-dev and removed request for a team April 23, 2026 09:41
Copy link
Copy Markdown
Contributor

@nfebe nfebe left a comment

Choose a reason for hiding this comment

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

Blocking because of the tests.

@nfebe
Copy link
Copy Markdown
Contributor

nfebe commented Apr 23, 2026

Moved to with better tests #59873

@nfebe nfebe closed this Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants