From 5357f2e94af110440c05a130fcb2afe9c65c2b4b Mon Sep 17 00:00:00 2001 From: Iva Horn Date: Wed, 29 Oct 2025 15:14:55 +0100 Subject: [PATCH] fix(file-provider): Share permissions. Signed-off-by: Iva Horn --- .../Extensions/NKShare+Extensions.swift | 29 ++-------- .../Sharing/ShareController.swift | 58 ++++++++----------- .../Sharing/ShareOptionsView.swift | 42 +++++++++----- 3 files changed, 56 insertions(+), 73 deletions(-) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Extensions/NKShare+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Extensions/NKShare+Extensions.swift index 8962a1db8eb5f..5dac1abf87760 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Extensions/NKShare+Extensions.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Extensions/NKShare+Extensions.swift @@ -10,26 +10,6 @@ import AppKit import NextcloudKit extension NKShare { - enum ShareType: Int { - case internalLink = -1 - case user = 0 - case group = 1 - case publicLink = 3 - case email = 4 - case federatedCloud = 6 - case team = 7 - case talkConversation = 10 - } - - enum PermissionValues: Int { - case readShare = 1 - case updateShare = 2 - case createShare = 4 - case deleteShare = 8 - case shareShare = 16 - case all = 31 - } - var typeImage: NSImage? { var image: NSImage? switch shareType { @@ -121,12 +101,15 @@ extension NKShare { } var shareesCanEdit: Bool { - get { (permissions & PermissionValues.updateShare.rawValue) != 0 } + get { + NKShare.Permission(rawValue: permissions).contains(.update) + } + set { if newValue { - permissions |= NKShare.PermissionValues.updateShare.rawValue + permissions = NKShare.Permission(rawValue: permissions).union(.update).rawValue } else { - permissions &= ~NKShare.PermissionValues.updateShare.rawValue + permissions = NKShare.Permission(rawValue: permissions).subtracting(.update).rawValue } } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareController.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareController.swift index 4f41154754113..6ca88bb9bde77 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareController.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareController.swift @@ -27,49 +27,37 @@ class ShareController: ObservableObject { shareWith: String?, password: String? = nil, expireDate: String? = nil, - permissions: Int = 1, - publicUpload: Bool = false, + permissions: NKShare.Permission, + publicUpload: Bool, note: String? = nil, label: String? = nil, hideDownload: Bool, attributes: String? = nil, options: NKRequestOptions = NKRequestOptions() ) async -> NKError? { - return await withCheckedContinuation { continuation in - if shareType == .publicLink { - kit.createShare( - path: itemServerRelativePath, - shareType: ShareType.publicLink.rawValue, - shareWith: nil, - publicUpload: publicUpload, - hideDownload: hideDownload, - password: password, - permissions: permissions, - account: account.ncKitAccount, - options: options - ) { account, share, data, error in - continuation.resume(returning: error) - } - } else { - guard let shareWith = shareWith else { - let error = NKError(statusCode: 0, fallbackDescription: "No recipient for share!") - continuation.resume(returning: error) - return - } + let sharee: String? = if shareType == .publicLink { + nil + } else { + shareWith + } - kit.createShare( - path: itemServerRelativePath, - shareType: shareType.rawValue, - shareWith: shareWith, - password: password, - permissions: permissions, - attributes: attributes, - account: account.ncKitAccount - ) { account, share, data, error in - continuation.resume(returning: error) - } - } + if shareType != .publicLink, sharee == nil { + // Any share requires a recipient, except public links. + return NKError(statusCode: 0, fallbackDescription: "No recipient for share!") } + + let (_, _, _, error) = await kit.createShareAsync( + path: itemServerRelativePath, + shareType: shareType.rawValue, + shareWith: sharee, + hideDownload: hideDownload, + password: password, + permissions: permissions.rawValue, + account: account.ncKitAccount, + options: options + ) + + return error } init(share: NKShare, account: Account, kit: NextcloudKit, log: any FileProviderLogging) { diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareOptionsView.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareOptionsView.swift index d56c9bd414702..5d1436b7ac3bd 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareOptionsView.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Sharing/ShareOptionsView.swift @@ -56,13 +56,14 @@ class ShareOptionsView: NSView { suggestionsTextFieldDelegate.suggestionsDataSource = ShareeSuggestionsDataSource(account: account, kit: kit, log: controller.log) - suggestionsTextFieldDelegate.confirmationHandler = { suggestion in - guard let sharee = suggestion?.data as? NKSharee else { - return + suggestionsTextFieldDelegate.confirmationHandler = { [weak self] suggestion in + Task { @MainActor in + guard let sharee = suggestion?.data as? NKSharee else { + return + } + self?.shareRecipientTextField.stringValue = sharee.shareWith + self?.logger?.debug("Chose sharee \(sharee.shareWith)") } - - self.shareRecipientTextField.stringValue = sharee.shareWith - self.logger?.debug("Chose sharee \(sharee.shareWith)") } suggestionsTextFieldDelegate.targetTextField = shareRecipientTextField @@ -190,7 +191,7 @@ class ShareOptionsView: NSView { if let caps = dataSource?.capabilities?.filesSharing { uploadEditPermissionCheckbox.state = - caps.defaultPermissions & NKShare.PermissionValues.updateShare.rawValue != 0 + caps.defaultPermissions & NKShare.Permission.update.rawValue != 0 ? .on : .off switch type { @@ -201,7 +202,7 @@ class ShareOptionsView: NSView { expirationDateCheckbox.state = caps.publicLink?.expireDateEnforced == true ? .on : .off expirationDateCheckbox.isEnabled = caps.publicLink?.expireDateEnforced == false expirationDatePicker.dateValue = Date( - timeIntervalSinceNow: + timeIntervalSinceNow: TimeInterval((caps.publicLink?.expireDateDays ?? 1) * 24 * 60 * 60) ) if caps.publicLink?.expireDateEnforced == true { @@ -281,12 +282,15 @@ class ShareOptionsView: NSView { let password = passwordProtectCheckbox.state == .on ? passwordSecureField.stringValue : "" + let expireDate = expirationDateCheckbox.state == .on ? NKShare.formattedDateString(date: expirationDatePicker.dateValue) : "" + let note = noteForRecipientCheckbox.state == .on ? noteTextField.stringValue : "" + let label = labelTextField.stringValue let hideDownload = hideDownloadCheckbox.state == .on let uploadAndEdit = uploadEditPermissionCheckbox.state == .on @@ -305,14 +309,17 @@ class ShareOptionsView: NSView { let selectedShareType = pickedShareType() let shareWith = shareRecipientTextField.stringValue - var permissions = NKShare.PermissionValues.all.rawValue - permissions = uploadAndEdit - ? permissions | NKShare.PermissionValues.updateShare.rawValue - : permissions & ~NKShare.PermissionValues.updateShare.rawValue + var permissions = NKShare.Permission.defaultPermission(for: selectedShareType) + + if uploadAndEdit { + permissions.formUnion(.create) + permissions.formUnion(.update) + } setAllFields(enabled: false) deleteButton.isEnabled = false saveButton.isEnabled = false + let error = await ShareController.create( account: account, kit: kit, @@ -322,10 +329,12 @@ class ShareOptionsView: NSView { password: password, expireDate: expireDate, permissions: permissions, + publicUpload: permissions.contains(.create), note: note, label: label, hideDownload: hideDownload ) + if let error = error, error != .success { dataSource.uiDelegate?.showError(String(localized: "Error creating: \(error.errorDescription)")) setAllFields(enabled: true) @@ -333,6 +342,7 @@ class ShareOptionsView: NSView { dataSource.uiDelegate?.hideOptions(self) await dataSource.reload() } + return } @@ -342,14 +352,16 @@ class ShareOptionsView: NSView { logger?.error("No valid share controller, cannot edit share.") return } + let share = controller.share let permissions = uploadAndEdit - ? share.permissions | NKShare.PermissionValues.updateShare.rawValue - : share.permissions & ~NKShare.PermissionValues.updateShare.rawValue + ? share.permissions | NKShare.Permission.update.rawValue + : share.permissions & ~NKShare.Permission.update.rawValue setAllFields(enabled: false) deleteButton.isEnabled = false saveButton.isEnabled = false + let error = await controller.save( password: password, expireDate: expireDate, @@ -358,6 +370,7 @@ class ShareOptionsView: NSView { label: label, hideDownload: hideDownload ) + if let error = error, error != .success { dataSource?.uiDelegate?.showError("Error updating share: \(error.errorDescription)") setAllFields(enabled: true) @@ -387,4 +400,3 @@ class ShareOptionsView: NSView { } } } -