Skip to content

Commit

Permalink
Added capabilities to manage share download limits.
Browse files Browse the repository at this point in the history
- Requesting share download limit capability of files_downloadlimit app.
- Augmented WebDAV metadata requests and responses with optional share download limits.
- Extended NextcloudKit with methods to manage share download limits via OCS.

Signed-off-by: Iva Horn <[email protected]>
  • Loading branch information
i2h3 committed Nov 21, 2024
1 parent 5ddf89c commit 3f2abc9
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 1 deletion.
33 changes: 33 additions & 0 deletions Sources/NextcloudKit/Models/NKDownloadLimit.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Nextcloud GmbH
// SPDX-FileCopyrightText: 2024 Iva Horn
// SPDX-License-Identifier: GPL-3.0-or-later

import Foundation

///
/// Data model for a download limit as returned in the WebDAV response for file properties.
///
/// Each relates to a share of a file and is optionally provided by the [Files Download Limit](https://github.com/nextcloud/files_downloadlimit) app for Nextcloud server.
///
public class NKDownloadLimit: NSObject {
///
/// The number of downloads which already happened.
///
public let count: Int

///
/// Total number of allowed downloas.
///
public let limit: Int

///
/// The token identifying the related share.
///
public let token: String

init(count: Int, limit: Int, token: String) {
self.count = count
self.limit = limit
self.token = token
}
}
6 changes: 6 additions & 0 deletions Sources/NextcloudKit/Models/NKFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ public class NKFile: NSObject {
public var date = Date()
public var directory: Bool = false
public var downloadURL = ""

///
/// Download limits for shares of this file.
///
public var downloadLimits = [NKDownloadLimit]()

public var e2eEncrypted: Bool = false
public var etag = ""
public var favorite: Bool = false
Expand Down
9 changes: 9 additions & 0 deletions Sources/NextcloudKit/Models/NKProperties.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
// SPDX-FileCopyrightText: 2023 Claudio Cambra
// SPDX-License-Identifier: GPL-3.0-or-later

///
/// Definition of properties used for decoding in ``NKDataFileXML``.
///
public enum NKProperties: String, CaseIterable {
/// DAV
case displayname = "<d:displayname />"

///
/// Download limits for shares of a file as optionally provided by the [Files Download Limit](https://github.com/nextcloud/files_downloadlimit) app for Nextcloud server.
///
case downloadLimit = "<nc:share-download-limits />"

case getlastmodified = "<d:getlastmodified />"
case getetag = "<d:getetag />"
case getcontenttype = "<d:getcontenttype />"
Expand Down
18 changes: 17 additions & 1 deletion Sources/NextcloudKit/NKDataFileXML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,23 @@ class NKDataFileXML: NSObject {
}

file.placePhotos = propstat["d:prop", "nc:metadata-photos-place"].text


for downloadLimit in propstat["d:prop", "nc:share-download-limits", "nc:share-download-limit"] {
guard let token = downloadLimit["nc:token"].text else {
continue
}

guard let limit = downloadLimit["nc:limit"].int else {
continue
}

guard let count = downloadLimit["nc:count"].int else {
continue
}

file.downloadLimits.append(NKDownloadLimit(count: count, limit: limit, token: token))
}

let results = self.nkCommonInstance.getInternalType(fileName: file.fileName, mimeType: file.contentType, directory: file.directory, account: nkSession.account)

file.contentType = results.mimeType
Expand Down
90 changes: 90 additions & 0 deletions Sources/NextcloudKit/NextcloudKit+ShareDownloadLimit.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-FileCopyrightText: Nextcloud GmbH
// SPDX-FileCopyrightText: 2024 Iva Horn
// SPDX-License-Identifier: GPL-3.0-or-later

import Alamofire
import Foundation

public extension NextcloudKit {
private func makeEndpoint(with token: String) -> String {
"ocs/v2.php/apps/files_downloadlimit/api/v1/\(token)/limit"
}

func removeShareDownloadLimit(account: String, token: String, completion: @escaping (_ error: NKError) -> Void) {
let endpoint = makeEndpoint(with: token)
let options = NKRequestOptions()

guard let nkSession = nkCommonInstance.getSession(account: account),
let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint, options: options),
let headers = nkCommonInstance.getStandardHeaders(account: account, options: options) else {
return options.queue.async {
completion(.urlError)
}
}

nkSession
.sessionData
.request(url, method: .delete, parameters: nil, encoding: URLEncoding.default, headers: headers, interceptor: nil)
.validate(statusCode: 200..<300)
.response(queue: self.nkCommonInstance.backgroundQueue) { response in
if self.nkCommonInstance.levelLog > 0 {
debugPrint(response)
}

switch response.result {
case .failure(let error):
let error = NKError(error: error, afResponse: response, responseData: response.data)

options.queue.async {
completion(error)
}
case .success:
options.queue.async {
completion(.success)
}
}
}
}

func setShareDownloadLimit(account: String, token: String, limit: Int, completion: @escaping (_ error: NKError) -> Void) {
let endpoint = makeEndpoint(with: token)
let options = NKRequestOptions()
options.contentType = "application/json"

guard let nkSession = nkCommonInstance.getSession(account: account),
let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint, options: options),
let headers = nkCommonInstance.getStandardHeaders(account: account, options: options),
var urlRequest = try? URLRequest(url: url, method: .put, headers: headers) else {
return options.queue.async {
completion(.urlError)
}
}

urlRequest.httpBody = try? JSONEncoder().encode([
"limit": limit
])

nkSession
.sessionData
.request(urlRequest)
.validate(statusCode: 200..<300)
.response(queue: self.nkCommonInstance.backgroundQueue) { response in
if self.nkCommonInstance.levelLog > 0 {
debugPrint(response)
}

switch response.result {
case .failure(let error):
let error = NKError(error: error, afResponse: response, responseData: response.data)

options.queue.async {
completion(error)
}
case .success:
options.queue.async {
completion(.success)
}
}
}
}
}

0 comments on commit 3f2abc9

Please sign in to comment.