From 7b42275dd7eea3d3ac416ea44f8e4abd5507d2ef Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Thu, 3 Jul 2025 17:05:47 +0200 Subject: [PATCH 1/3] async wrapper Signed-off-by: Marino Faggiana --- Sources/NextcloudKit/NextcloudKit+Share.swift | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Sources/NextcloudKit/NextcloudKit+Share.swift b/Sources/NextcloudKit/NextcloudKit+Share.swift index 01ea7d74..520866d4 100644 --- a/Sources/NextcloudKit/NextcloudKit+Share.swift +++ b/Sources/NextcloudKit/NextcloudKit+Share.swift @@ -93,6 +93,39 @@ public extension NextcloudKit { } } + /// Asynchronously reads shares for a given account using the provided parameters. + /// - Parameters: + /// - parameters: The `NKShareParameter` object containing filters and options for the request. + /// - account: The account identifier for which to fetch shares. + /// - options: Optional `NKRequestOptions` to customize the request (default is empty). + /// - taskHandler: Closure called when the underlying `URLSessionTask` is created, useful for tracking or cancellation. + /// - Returns: A tuple containing: + /// - `account`: The account used for the request. + /// - `shares`: An optional array of `NKShare` objects returned by the server. + /// - `responseData`: The raw Alamofire response object. + /// - `error`: An `NKError` indicating the result of the request. + func readSharesAsync(parameters: NKShareParameter, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }) async -> (account: String, shares: [NKShare]?, responseData: AFDataResponse?, error: NKError) { + + await withCheckedContinuation { continuation in + readShares( + parameters: parameters, + account: account, + options: options, + taskHandler: taskHandler + ) { account, shares, responseData, error in + continuation.resume(returning: ( + account: account, + shares: shares, + responseData: responseData, + error: error + )) + } + } + } + /* * @param search The search string * @param itemType The type which is shared (e.g. file or folder) From 15c1fa20d203dba4817521466da5b2436b3bc8d0 Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Fri, 4 Jul 2025 08:05:20 +0200 Subject: [PATCH 2/3] async Signed-off-by: Marino Faggiana --- Sources/NextcloudKit/NextcloudKit+Share.swift | 233 ++++++++++++++++-- 1 file changed, 215 insertions(+), 18 deletions(-) diff --git a/Sources/NextcloudKit/NextcloudKit+Share.swift b/Sources/NextcloudKit/NextcloudKit+Share.swift index 520866d4..78dc8695 100644 --- a/Sources/NextcloudKit/NextcloudKit+Share.swift +++ b/Sources/NextcloudKit/NextcloudKit+Share.swift @@ -229,6 +229,57 @@ public extension NextcloudKit { } } + /// Searches for sharees (users, groups, etc.) that can be shared with, using the provided parameters. + /// This function performs a paginated server-side lookup of sharees for a given account. + /// - Parameters: + /// - search: The search string used to filter sharees (default is empty string). + /// - page: The current page for pagination (default is 1). + /// - perPage: The number of results per page (default is 200). + /// - itemType: The type of item to be shared (e.g., "file"). + /// - lookup: Whether to enable extended lookup on the server (default is false). + /// - account: The account identifier associated with the request. + /// - options: Optional request parameters (default is `.init()`). + /// - Returns: A tuple containing: + /// - account: The associated account string. + /// - sharees: An optional array of `NKSharee` objects returned by the server. + /// - responseData: The full `AFDataResponse` from Alamofire. + /// - error: An `NKError` object representing success or failure. + func searchShareesAsync( + search: String = "", + page: Int = 1, + perPage: Int = 200, + itemType: String = "file", + lookup: Bool = false, + account: String, + options: NKRequestOptions = NKRequestOptions() + ) async -> ( + account: String, + sharees: [NKSharee]?, + responseData: AFDataResponse?, + error: NKError + ) { + await withCheckedContinuation { continuation in + searchSharees( + search: search, + page: page, + perPage: perPage, + itemType: itemType, + lookup: lookup, + account: account, + options: options, + taskHandler: { _ in }, + completion: { account, sharees, responseData, error in + continuation.resume(returning: ( + account: account, + sharees: sharees, + responseData: responseData, + error: error + )) + } + ) + } + } + /* * @param path path of the file/folder being shared. Mandatory argument * @param shareType 0 = user, 1 = group, 3 = Public link. Mandatory argument @@ -248,6 +299,7 @@ public extension NextcloudKit { * @param attributes There is currently only one share attribute “download” from the scope “permissions”. This attribute is only valid for user and group shares, not for public link shares. */ + /* func createShareLink(path: String, hideDownload: Bool = false, publicUpload: Bool = false, @@ -264,25 +316,8 @@ public extension NextcloudKit { completion(account, share, responseData, error) } } + */ - func createShare(path: String, - shareType: Int, - shareWith: String, - password: String? = nil, - note: String? = nil, - permissions: Int = 1, - attributes: String? = nil, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ share: NKShare?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { - createShare(path: path, shareType: shareType, shareWith: shareWith, publicUpload: false, note: note, hideDownload: false, password: password, permissions: permissions, attributes: attributes, account: account, options: options) { task in - task.taskDescription = options.taskDescription - taskHandler(task) - } completion: { account, share, responseData, error in - completion(account, share, responseData, error) - } - } private func createShare(path: String, shareType: Int, @@ -347,6 +382,69 @@ public extension NextcloudKit { } } + /// Creates a new share for the specified path and parameters, such as share type, target, permissions, and options. + /// This function performs a network request to the server to create the share. + /// - Parameters: + /// - path: The file or folder path to be shared. + /// - shareType: The type of share (e.g., 0=user, 1=group, 3=public link). + /// - shareWith: The recipient (username, group name, or nil for public). + /// - publicUpload: Whether to allow public upload (if applicable). + /// - note: Optional note associated with the share. + /// - hideDownload: Whether to hide the download option (if supported). + /// - password: Optional password for protected shares. + /// - permissions: Bitmask representing share permissions (default is 1 = read). + /// - attributes: Optional extended attributes as string. + /// - account: The account making the request. + /// - options: Optional request options (default is `.init()`). + /// - Returns: A tuple containing: + /// - account: The account string. + /// - share: An optional `NKShare` object representing the created share. + /// - responseData: The raw `AFDataResponse` returned by Alamofire. + /// - error: An `NKError` representing the result of the operation. + private func createShareAsync( + path: String, + shareType: Int, + shareWith: String?, + publicUpload: Bool? = nil, + note: String? = nil, + hideDownload: Bool? = nil, + password: String? = nil, + permissions: Int = 1, + attributes: String? = nil, + account: String, + options: NKRequestOptions = NKRequestOptions() + ) async -> ( + account: String, + share: NKShare?, + responseData: AFDataResponse?, + error: NKError + ) { + await withCheckedContinuation { continuation in + createShare( + path: path, + shareType: shareType, + shareWith: shareWith, + publicUpload: publicUpload, + note: note, + hideDownload: hideDownload, + password: password, + permissions: permissions, + attributes: attributes, + account: account, + options: options, + taskHandler: { _ in }, + completion: { account, share, responseData, error in + continuation.resume(returning: ( + account: account, + share: share, + responseData: responseData, + error: error + )) + } + ) + } + } + /* * @param idShare Identifier of the share to update * @param password Password to protect a public link share. Only available for public link shares, Empty string clears the current password, Null results in no update applied to the password @@ -431,6 +529,69 @@ public extension NextcloudKit { } } + /// Updates the parameters of an existing share identified by its ID. + /// Allows changing settings like password, expiration, permissions, public upload, note, label, etc. + /// - Parameters: + /// - idShare: The ID of the share to be updated. + /// - password: Optional new password for the share. + /// - expireDate: Optional new expiration date (in string format). + /// - permissions: Bitmask representing new share permissions (default is 1 = read). + /// - publicUpload: Whether public upload is enabled for the share. + /// - note: Optional note for the share. + /// - label: Optional label for identifying the share. + /// - hideDownload: Whether the download option should be hidden. + /// - attributes: Optional string of encoded attributes. + /// - account: The account performing the update. + /// - options: Optional request options (default is `.init()`). + /// - Returns: A tuple containing: + /// - account: The account string. + /// - share: The updated `NKShare` object, or nil on failure. + /// - responseData: The raw `AFDataResponse` returned by Alamofire. + /// - error: An `NKError` representing the outcome of the operation. + func updateShareAsync( + idShare: Int, + password: String? = nil, + expireDate: String? = nil, + permissions: Int = 1, + publicUpload: Bool? = nil, + note: String? = nil, + label: String? = nil, + hideDownload: Bool, + attributes: String? = nil, + account: String, + options: NKRequestOptions = NKRequestOptions() + ) async -> ( + account: String, + share: NKShare?, + responseData: AFDataResponse?, + error: NKError + ) { + await withCheckedContinuation { continuation in + updateShare( + idShare: idShare, + password: password, + expireDate: expireDate, + permissions: permissions, + publicUpload: publicUpload, + note: note, + label: label, + hideDownload: hideDownload, + attributes: attributes, + account: account, + options: options, + taskHandler: { _ in }, + completion: { account, share, responseData, error in + continuation.resume(returning: ( + account: account, + share: share, + responseData: responseData, + error: error + )) + } + ) + } + } + /* * @param idShare: Identifier of the share to update */ @@ -458,6 +619,42 @@ public extension NextcloudKit { } } + /// Deletes an existing share on the server using its share ID. + /// This function sends a network request to remove the share for the specified account. + /// - Parameters: + /// - idShare: The ID of the share to delete. + /// - account: The account initiating the deletion request. + /// - options: Optional request options (default is `.init()`). + /// - Returns: A tuple containing: + /// - account: The account string used for the request. + /// - responseData: The full `AFDataResponse` returned from the server. + /// - error: An `NKError` representing the result of the deletion operation. + func deleteShareAsync( + idShare: Int, + account: String, + options: NKRequestOptions = NKRequestOptions() + ) async -> ( + account: String, + responseData: AFDataResponse?, + error: NKError + ) { + await withCheckedContinuation { continuation in + deleteShare( + idShare: idShare, + account: account, + options: options, + taskHandler: { _ in }, + completion: { account, responseData, error in + continuation.resume(returning: ( + account: account, + responseData: responseData, + error: error + )) + } + ) + } + } + // MARK: - private func convertResponseShare(json: JSON, account: String) -> NKShare { From 92b0fb51b487c29353eb821e897cfe80c3f39a90 Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Fri, 4 Jul 2025 08:07:50 +0200 Subject: [PATCH 3/3] async Signed-off-by: Marino Faggiana --- Sources/NextcloudKit/NextcloudKit+Share.swift | 46 ++++++------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/Sources/NextcloudKit/NextcloudKit+Share.swift b/Sources/NextcloudKit/NextcloudKit+Share.swift index 78dc8695..df563ee2 100644 --- a/Sources/NextcloudKit/NextcloudKit+Share.swift +++ b/Sources/NextcloudKit/NextcloudKit+Share.swift @@ -299,39 +299,19 @@ public extension NextcloudKit { * @param attributes There is currently only one share attribute “download” from the scope “permissions”. This attribute is only valid for user and group shares, not for public link shares. */ - /* - func createShareLink(path: String, - hideDownload: Bool = false, - publicUpload: Bool = false, - password: String? = nil, - permissions: Int = 1, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ share: NKShare?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { - createShare(path: path, shareType: 3, shareWith: nil, publicUpload: publicUpload, hideDownload: hideDownload, password: password, permissions: permissions, account: account, options: options) { task in - task.taskDescription = options.taskDescription - taskHandler(task) - } completion: { account, share, responseData, error in - completion(account, share, responseData, error) - } - } - */ - - - private func createShare(path: String, - shareType: Int, - shareWith: String?, - publicUpload: Bool? = nil, - note: String? = nil, - hideDownload: Bool? = nil, - password: String? = nil, - permissions: Int = 1, - attributes: String? = nil, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ share: NKShare?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + func createShare(path: String, + shareType: Int, + shareWith: String?, + publicUpload: Bool? = nil, + note: String? = nil, + hideDownload: Bool? = nil, + password: String? = nil, + permissions: Int = 1, + attributes: String? = nil, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ share: NKShare?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { let endpoint = "ocs/v2.php/apps/files_sharing/api/v1/shares" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint, options: options),