Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
290 changes: 250 additions & 40 deletions Sources/NextcloudKit/NextcloudKit+Share.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Data>?, 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)
Expand Down Expand Up @@ -196,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<Data>` 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<Data>?,
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
Expand All @@ -215,55 +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<Data>?, _ 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)
}
}

func createShare(path: String,
shareType: Int,
shareWith: String,
password: String? = nil,
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<Data>?, _ 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,
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<Data>?, _ 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),
Expand Down Expand Up @@ -314,6 +362,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<Data>` 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<Data>?,
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
Expand Down Expand Up @@ -398,6 +509,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<Data>` 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<Data>?,
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
*/
Expand Down Expand Up @@ -425,6 +599,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<Data>` 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<Data>?,
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 {
Expand Down
Loading