Skip to content

Commit

Permalink
Merge pull request #22 from claucambra/bugfix/improve-authentication-…
Browse files Browse the repository at this point in the history
…loop

Add new utility methods to remote interface for auth purposes
  • Loading branch information
claucambra authored Sep 30, 2024
2 parents 3690760 + 9c7a6b0 commit bb36e8e
Show file tree
Hide file tree
Showing 15 changed files with 114 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extension NextcloudKit: RemoteInterface {
public var account: Account {
Account(
user: nkCommonInstance.user,
id: nkCommonInstance.userId,
serverUrl: nkCommonInstance.urlBase,
password: nkCommonInstance.password
)
Expand Down Expand Up @@ -202,4 +203,34 @@ extension NextcloudKit: RemoteInterface {
}
}
}

public func fetchUserProfile(
options: NKRequestOptions = .init(),
taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }
) async -> (account: String, userProfile: NKUserProfile?, data: Data?, error: NKError) {
return await withCheckedContinuation { continuation in
getUserProfile(
options: options, taskHandler: taskHandler
) { account, userProfile, data, error in
continuation.resume(returning: (account, userProfile, data, error))
}
}
}

public func tryAuthenticationAttempt(
options: NKRequestOptions = .init(),
taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }
) async -> AuthenticationAttemptResultState {
// Test by trying to fetch user profile
let (_, _, _, error) =
await fetchUserProfile(options: options, taskHandler: taskHandler)

if error == .success {
return .success
} else if error.isCouldntConnectError {
return .connectionError
} else {
return .authenticationError
}
}
}
12 changes: 12 additions & 0 deletions Sources/NextcloudFileProviderKit/Interface/RemoteInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ public enum EnumerateDepth: String {
case targetAndAllChildren = "infinity"
}

public enum AuthenticationAttemptResultState: Int {
case authenticationError, connectionError, success
}

public protocol RemoteInterface {

var account: Account { get }
Expand Down Expand Up @@ -98,4 +102,12 @@ public protocol RemoteInterface {
func fetchCapabilities(
options: NKRequestOptions, taskHandler: @escaping (_ task: URLSessionTask) -> Void
) async -> (account: String, data: Data?, error: NKError)

func fetchUserProfile(
options: NKRequestOptions, taskHandler: @escaping (_ task: URLSessionTask) -> Void
) async -> (account: String, userProfile: NKUserProfile?, data: Data?, error: NKError)

func tryAuthenticationAttempt(
options: NKRequestOptions, taskHandler: @escaping (_ task: URLSessionTask) -> Void
) async -> AuthenticationAttemptResultState
}
4 changes: 0 additions & 4 deletions Sources/NextcloudFileProviderKit/Item/Item.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,6 @@ public class Item: NSObject, NSFileProviderItem {
dbManager: FilesDatabaseManager = .shared
) -> Item? {
// resolve the given identifier to a record in the model
Self.logger.debug(
"Received request for item with identifier: \(identifier.rawValue, privacy: .public)"
)

guard identifier != .rootContainer else {
return Item.rootContainer(remoteInterface: remoteInterface)
}
Expand Down
8 changes: 6 additions & 2 deletions Sources/NextcloudFileProviderKit/Utilities/Account.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@
import Foundation

let AccountDictUsernameKey = "usernameKey"
let AccountDictIdKey = "idKey"
let AccountDictPasswordKey = "passwordKey"
let AccountDictNcKitAccountKey = "ncKitAccountKey"
let AccountDictServerUrlKey = "serverUrlKey"
let AccountDictDavFilesUrlKey = "davFilesUrlKey"

public struct Account: Equatable {
public static let webDavFilesUrlSuffix: String = "/remote.php/dav/files/"
public let username, password, ncKitAccount, serverUrl, davFilesUrl: String
public let username, id, password, ncKitAccount, serverUrl, davFilesUrl: String

public init(user: String, serverUrl: String, password: String) {
public init(user: String, id: String, serverUrl: String, password: String) {
username = user
self.id = id
self.password = password
ncKitAccount = user + " " + serverUrl
self.serverUrl = serverUrl
Expand All @@ -34,6 +36,7 @@ public struct Account: Equatable {

public init?(dictionary: Dictionary<String, String>) {
guard let username = dictionary[AccountDictUsernameKey],
let id = dictionary[AccountDictIdKey],
let password = dictionary[AccountDictPasswordKey],
let ncKitAccount = dictionary[AccountDictNcKitAccountKey],
let serverUrl = dictionary[AccountDictServerUrlKey],
Expand All @@ -43,6 +46,7 @@ public struct Account: Equatable {
}

self.username = username
self.id = id
self.password = password
self.ncKitAccount = ncKitAccount
self.serverUrl = serverUrl
Expand Down
19 changes: 19 additions & 0 deletions Tests/Interface/MockRemoteInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,23 @@ public class MockRemoteInterface: RemoteInterface {
) async -> (account: String, data: Data?, error: NKError) {
return (accountString, capabilities.data(using: .utf8), .success)
}

public func fetchUserProfile(
options: NKRequestOptions = .init(),
taskHandler: @escaping (URLSessionTask) -> Void = { _ in }
) async -> (account: String, userProfile: NKUserProfile?, data: Data?, error: NKError) {
let profile = NKUserProfile()
profile.address = account.serverUrl
profile.backend = "mock"
profile.displayName = account.ncKitAccount
profile.userId = account.username
return (account.ncKitAccount, profile, nil, .success)
}

public func tryAuthenticationAttempt(
options: NKRequestOptions = .init(),
taskHandler: @escaping (URLSessionTask) -> Void = { _ in }
) async -> AuthenticationAttemptResultState {
return account.password.isEmpty ? .authenticationError : .success
}
}
20 changes: 19 additions & 1 deletion Tests/InterfaceTests/MockRemoteInterfaceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import XCTest

final class MockRemoteInterfaceTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)
lazy var rootItem = MockRemoteItem(
identifier: "root",
Expand Down Expand Up @@ -425,4 +425,22 @@ final class MockRemoteInterfaceTests: XCTestCase {
XCTAssertEqual(result.error, .success)
XCTAssertEqual(itemA.children, [])
}

func testFetchUserProfile() async {
let remoteInterface = MockRemoteInterface(account: Self.account, rootItem: rootItem)
let (account, profile, _, error) = await remoteInterface.fetchUserProfile()
XCTAssertEqual(error, .success)
XCTAssertEqual(account, Self.account.ncKitAccount)
XCTAssertNotNil(profile)
}

func testTryAuthenticationAttempt() async {
let remoteInterface = MockRemoteInterface(account: Self.account, rootItem: rootItem)
let state = await remoteInterface.tryAuthenticationAttempt()
XCTAssertEqual(state, .success)
let newMri =
MockRemoteInterface(account: Account(user: "", id: "", serverUrl: "", password: ""))
let failState = await newMri.tryAuthenticationAttempt()
XCTAssertEqual(failState, .authenticationError)
}
}
19 changes: 14 additions & 5 deletions Tests/NextcloudFileProviderKitTests/AccountTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import XCTest
final class AccountTests: XCTest {
func testInitializationDirect() {
let user = "user"
let userId = "userId"
let password = "password"
let serverUrl = "https://example.com"
let account = Account(user: user, serverUrl: serverUrl, password: password)
let account = Account(user: user, id: userId, serverUrl: serverUrl, password: password)

XCTAssertEqual(account.username, user)
XCTAssertEqual(account.password, password)
Expand Down Expand Up @@ -53,7 +54,9 @@ final class AccountTests: XCTest {
}

func testDictionaryRepresentation() {
let account = Account(user: "user", serverUrl: "https://example.com", password: "password")
let account = Account(
user: "user", id: "userId", serverUrl: "https://example.com", password: "password"
)
let dictionary = account.dictionary()

XCTAssertEqual(dictionary[AccountDictUsernameKey], "user")
Expand All @@ -64,12 +67,18 @@ final class AccountTests: XCTest {
}

func testEquatability() {
let account1 = Account(user: "user", serverUrl: "https://example.com", password: "password")
let account2 = Account(user: "user", serverUrl: "https://example.com", password: "password")
let account1 = Account(
user: "user", id: "userId", serverUrl: "https://example.com", password: "password"
)
let account2 = Account(
user: "user", id: "userId", serverUrl: "https://example.com", password: "password"
)

XCTAssertEqual(account1, account2)

let account3 = Account(user: "user", serverUrl: "https://example.net", password: "password")
let account3 = Account(
user: "user", id: "userId", serverUrl: "https://example.net", password: "password"
)
XCTAssertNotEqual(account1, account3)
}
}
2 changes: 1 addition & 1 deletion Tests/NextcloudFileProviderKitTests/EnumeratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import XCTest

final class EnumeratorTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)

var rootItem: MockRemoteItem!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import XCTest

final class FilesDatabaseManagerTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)

static let dbManager = FilesDatabaseManager(realmConfig: .defaultConfiguration)
Expand Down
2 changes: 1 addition & 1 deletion Tests/NextcloudFileProviderKitTests/ItemCreateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import XCTest

final class ItemCreateTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)

lazy var rootItem = MockRemoteItem(
Expand Down
2 changes: 1 addition & 1 deletion Tests/NextcloudFileProviderKitTests/ItemDeleteTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import XCTest

final class ItemDeleteTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)
lazy var rootItem = MockRemoteItem(
identifier: NSFileProviderItemIdentifier.rootContainer.rawValue,
Expand Down
2 changes: 1 addition & 1 deletion Tests/NextcloudFileProviderKitTests/ItemFetchTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import XCTest

final class ItemFetchTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)

lazy var rootItem = MockRemoteItem(
Expand Down
2 changes: 1 addition & 1 deletion Tests/NextcloudFileProviderKitTests/ItemModifyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import XCTest

final class ItemModifyTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)

lazy var rootItem = MockRemoteItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import XCTest

final class ItemPropertyTests: XCTestCase {
static let account = Account(
user: "testUser", serverUrl: "https://mock.nc.com", password: "abcd"
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)

func testMetadataContentType() {
Expand Down
Loading

0 comments on commit bb36e8e

Please sign in to comment.