Skip to content
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import NextcloudKit
import NextcloudFileProviderKit
import OSLog

let AuthenticationTimeouts: [UInt64] = [ // Have progressively longer timeouts to not hammer server
3_000_000_000, 6_000_000_000, 30_000_000_000, 60_000_000_000, 120_000_000_000, 300_000_000_000
]

extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInterface {
/*
This FileProviderExtension extension contains everything needed to communicate with the client.
Expand Down Expand Up @@ -100,14 +104,57 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte
}
}

@objc func setupDomainAccount(user: String, serverUrl: String, password: String) {
let newNcAccount = Account(user: user, serverUrl: serverUrl, password: password)
@objc func setupDomainAccount(
user: String, userId: String, serverUrl: String, password: String
) {
let semaphore = DispatchSemaphore(value: 0)
var authAttemptState = AuthenticationAttemptResultState.connectionError // default
Task {
let authTestNcKit = NextcloudKit()
authTestNcKit.setup(user: user, userId: userId, password: password, urlBase: serverUrl)

// Retry a few times if we have a connection issue
for authTimeout in AuthenticationTimeouts {
authAttemptState = await authTestNcKit.tryAuthenticationAttempt()
guard authAttemptState == .connectionError else { break }

Logger.fileProviderExtension.info(
"\(user, privacy: .public) authentication try timed out. Trying again soon."
)
try? await Task.sleep(nanoseconds: authTimeout)
}
semaphore.signal()
}
semaphore.wait()

switch (authAttemptState) {
case .authenticationError:
Logger.fileProviderExtension.info(
"\(user, privacy: .public) authentication failed due to bad creds, stopping"
)
return
case .connectionError:
// Despite multiple connection attempts we are still getting connection issues, so quit.
Logger.fileProviderExtension.info(
"\(user, privacy: .public) authentication try failed, no connection."
)
return
case .success:
Logger.fileProviderExtension.info(
"""
Authenticated! Nextcloud account set up in File Provider extension.
User: \(user, privacy: .public) at server: \(serverUrl, privacy: .public)
"""
)
}

let newNcAccount = Account(user: user, id: userId, serverUrl: serverUrl, password: password)
guard newNcAccount != ncAccount else { return }
ncAccount = newNcAccount
ncKit.setup(
account: newNcAccount.ncKitAccount,
user: newNcAccount.username,
userId: newNcAccount.username,
userId: newNcAccount.id,
password: newNcAccount.password,
urlBase: newNcAccount.serverUrl,
userAgent: "Nextcloud-macOS/FileProviderExt",
Expand All @@ -118,11 +165,6 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte
remoteInterface: ncKit, changeNotificationInterface: self, domain: domain
)
ncKit.setup(delegate: changeObserver)

Logger.fileProviderExtension.info(
"Nextcloud account set up in File Provider extension for user: \(user, privacy: .public) at server: \(serverUrl, privacy: .public)"
)

signalEnumeratorAfterAccountSetup()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ class FileProviderSocketLineProcessor: NSObject, LineProcessor {
delegate.removeAccountConfig()
} else if command == "ACCOUNT_DETAILS" {
guard let accountDetailsSubsequence = splitLine.last else { return }
let splitAccountDetails = accountDetailsSubsequence.split(separator: "~", maxSplits: 2)
let splitAccountDetails = accountDetailsSubsequence.split(separator: "~", maxSplits: 3)

let user = String(splitAccountDetails[0])
let serverUrl = String(splitAccountDetails[1])
let password = String(splitAccountDetails[2])
let userId = String(splitAccountDetails[1])
let serverUrl = String(splitAccountDetails[2])
let password = String(splitAccountDetails[3])

delegate.setupDomainAccount(user: user, serverUrl: serverUrl, password: password)
delegate.setupDomainAccount(user: user, userId: userId, serverUrl: serverUrl, password: password)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

- (void)getExtensionAccountIdWithCompletionHandler:(void(^)(NSString *extensionAccountId, NSError *error))completionHandler;
- (void)configureAccountWithUser:(NSString *)user
userId:(NSString *)userId
serverUrl:(NSString *)serverUrl
password:(NSString *)password;
- (void)removeAccountConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ class ClientCommunicationService: NSObject, NSFileProviderServiceSource, NSXPCLi
completionHandler(accountUserId, nil)
}

func configureAccount(withUser user: String,
func configureAccount(withUser user: String,
userId: String,
serverUrl: String,
password: String) {
Logger.desktopClientConnection.info("Received configure account information over client communication service")
self.fpExtension.setupDomainAccount(user: user,
userId: userId,
serverUrl: serverUrl,
password: password)
}
Expand Down
8 changes: 5 additions & 3 deletions src/gui/macOS/fileprovidersocketcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,15 @@ void FileProviderSocketController::sendAccountDetails() const

const auto credentials = account->credentials();
Q_ASSERT(credentials);
const auto accountUser = account->davUser();
const auto accountUrl = account->url().toString();
const auto accountPassword = credentials->password();
const auto accountUser = credentials->user(); // User-provided username/email
const auto accountUserId = account->davUser(); // Backing user id on server
const auto accountUrl = account->url().toString(); // Server base URL
const auto accountPassword = credentials->password(); // Account password

// We cannot use colons as separators here due to "https://" in the url
const auto message = QString(QStringLiteral("ACCOUNT_DETAILS:") +
accountUser + "~" +
accountUserId + "~" +
accountUrl + "~" +
accountPassword);
sendMessage(message);
Expand Down
2 changes: 2 additions & 0 deletions src/gui/macOS/fileproviderxpc_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@
const auto account = accountState->account();
const auto credentials = account->credentials();
NSString *const user = credentials->user().toNSString();
NSString *const userId = account->davUser().toNSString();
NSString *const serverUrl = account->url().toString().toNSString();
NSString *const password = credentials->password().toNSString();

const auto clientCommService = (NSObject<ClientCommunicationProtocol> *)_clientCommServices.value(extensionAccountId);
[clientCommService configureAccountWithUser:user
userId:userId
serverUrl:serverUrl
password:password];
}
Expand Down