Skip to content

Commit

Permalink
Merge pull request #2 from claucambra/feature/locking
Browse files Browse the repository at this point in the history
Add support for remote file locking
  • Loading branch information
claucambra committed Jun 12, 2024
2 parents fa8bee3 + 91c7d84 commit cce07d1
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Sources/NextcloudFileProviderKit/Item/Item.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ public class Item: NSObject, NSFileProviderItem {
}
}

public var fileSystemFlags: NSFileProviderFileSystemFlags {
if metadata.lock,
metadata.lockOwner != metadata.userId,
metadata.lockTimeOut ?? Date() > Date()
{
return [.userReadable]
}
return [.userReadable, .userWritable]
}

@available(macOS 13.0, *)
public var contentPolicy: NSFileProviderContentPolicy {
#if os(macOS)
Expand Down
15 changes: 15 additions & 0 deletions Tests/Interface/MockRemoteItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class MockRemoteItem: Equatable {
public let creationDate: Date
public var modificationDate: Date
public var data: Data?
public var locked: Bool
public var lockOwner: String
public var lockTimeOut: Date?
public var size: Int64 { Int64(data?.count ?? 0) }
public var account: String
public var username: String
Expand All @@ -37,6 +40,9 @@ public class MockRemoteItem: Equatable {
file.user = username
file.userId = username
file.urlBase = serverUrl
file.lock = locked
file.lockOwner = lockOwner
file.lockTimeOut = lockTimeOut
return file
}

Expand All @@ -47,6 +53,9 @@ public class MockRemoteItem: Equatable {
lhs.versionIdentifier == rhs.versionIdentifier &&
lhs.name == rhs.name &&
lhs.directory == rhs.directory &&
lhs.locked == rhs.locked &&
lhs.lockOwner == rhs.lockOwner &&
lhs.lockTimeOut == rhs.lockTimeOut &&
lhs.data == rhs.data &&
lhs.size == rhs.size &&
lhs.creationDate == rhs.creationDate &&
Expand All @@ -65,6 +74,9 @@ public class MockRemoteItem: Equatable {
creationDate: Date = Date(),
modificationDate: Date = Date(),
data: Data? = nil,
locked: Bool = false,
lockOwner: String = "",
lockTimeOut: Date? = nil,
account: String,
username: String,
serverUrl: String
Expand All @@ -77,6 +89,9 @@ public class MockRemoteItem: Equatable {
self.creationDate = creationDate
self.modificationDate = modificationDate
self.data = data
self.locked = locked
self.lockOwner = lockOwner
self.lockTimeOut = lockTimeOut
self.account = account
self.username = username
self.serverUrl = serverUrl
Expand Down
96 changes: 96 additions & 0 deletions Tests/NextcloudFileProviderKitTests/EnumeratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -570,4 +570,100 @@ final class EnumeratorTests: XCTestCase {
storedFolder.dbManager = Self.dbManager
XCTAssertEqual(storedFolder.childItemCount?.intValue, remoteFolder.children.count)
}

func testFileLockStateEnumeration() async throws {
let remoteInterface = MockRemoteInterface(account: Self.account, rootItem: rootItem)

remoteFolder.children.append(remoteItemC)
remoteItemC.parent = remoteFolder

remoteItemA.locked = true
remoteItemA.lockOwner = Self.account.username
remoteItemA.lockTimeOut = Date.now.advanced(by: 1_000_000_000_000)

remoteItemB.locked = true
remoteItemB.lockOwner = "other different account"
remoteItemB.lockTimeOut = Date.now.advanced(by: 1_000_000_000_000)

remoteItemC.locked = true
remoteItemC.lockOwner = "other different account"
remoteItemC.lockTimeOut = Date.now.advanced(by: -1_000_000_000_000)

let folderMetadata = ItemMetadata()
folderMetadata.ocId = remoteFolder.identifier
folderMetadata.etag = "OLD"
folderMetadata.directory = true
folderMetadata.name = remoteFolder.name
folderMetadata.fileName = remoteFolder.name
folderMetadata.fileNameView = remoteFolder.name
folderMetadata.serverUrl = Self.account.davFilesUrl
folderMetadata.account = Self.account.ncKitAccount
folderMetadata.user = Self.account.username
folderMetadata.userId = Self.account.username
folderMetadata.urlBase = Self.account.serverUrl

Self.dbManager.addItemMetadata(folderMetadata)
XCTAssertNotNil(Self.dbManager.itemMetadataFromOcId(remoteFolder.identifier))

let enumerator = Enumerator(
enumeratedItemIdentifier: .init(remoteFolder.identifier),
ncAccount: Self.account,
remoteInterface: remoteInterface,
dbManager: Self.dbManager
)
let observer = MockChangeObserver(enumerator: enumerator)
try await observer.enumerateChanges()
XCTAssertEqual(observer.changedItems.count, 3)

let dbItemAMetadata = try XCTUnwrap(
Self.dbManager.itemMetadataFromOcId(remoteItemA.identifier)
)
let dbItemBMetadata = try XCTUnwrap(
Self.dbManager.itemMetadataFromOcId(remoteItemB.identifier)
)
let dbItemCMetadata = try XCTUnwrap(
Self.dbManager.itemMetadataFromOcId(remoteItemC.identifier)
)

XCTAssertEqual(dbItemAMetadata.lock, remoteItemA.locked)
XCTAssertEqual(dbItemAMetadata.lockOwner, remoteItemA.lockOwner)
XCTAssertEqual(dbItemAMetadata.lockTimeOut, remoteItemA.lockTimeOut)

XCTAssertEqual(dbItemBMetadata.lock, remoteItemB.locked)
XCTAssertEqual(dbItemBMetadata.lockOwner, remoteItemB.lockOwner)
XCTAssertEqual(dbItemBMetadata.lockTimeOut, remoteItemB.lockTimeOut)

XCTAssertEqual(dbItemCMetadata.lock, remoteItemC.locked)
XCTAssertEqual(dbItemCMetadata.lockOwner, remoteItemC.lockOwner)
XCTAssertEqual(dbItemCMetadata.lockTimeOut, remoteItemC.lockTimeOut)

let storedItemA = try XCTUnwrap(
Item.storedItem(
identifier: .init(remoteItemA.identifier),
remoteInterface: remoteInterface,
dbManager: Self.dbManager
)
)
let storedItemB = try XCTUnwrap(
Item.storedItem(
identifier: .init(remoteItemB.identifier),
remoteInterface: remoteInterface,
dbManager: Self.dbManager
)
)
let storedItemC = try XCTUnwrap(
Item.storedItem(
identifier: .init(remoteItemC.identifier),
remoteInterface: remoteInterface,
dbManager: Self.dbManager
)
)

// Should be able to write to files locked by self
XCTAssertTrue(storedItemA.fileSystemFlags.contains(.userWritable))
// Should not be able to write to files locked by someone else
XCTAssertFalse(storedItemB.fileSystemFlags.contains(.userWritable))
// Should be able to write to files with an expired lock
XCTAssertTrue(storedItemC.fileSystemFlags.contains(.userWritable))
}
}

0 comments on commit cce07d1

Please sign in to comment.