From 228969242239fd9705ee64eb404259c5794bcfac Mon Sep 17 00:00:00 2001 From: Andrew Erickson Date: Sat, 1 May 2021 09:12:36 -0600 Subject: [PATCH 1/2] show auth errors inline on sign in view --- Xcodes/Backend/AppState.swift | 1 + Xcodes/Frontend/MainWindow.swift | 1 + .../SignIn/SignInCredentialsView.swift | 29 ++++++++++++++----- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Xcodes/Backend/AppState.swift b/Xcodes/Backend/AppState.swift index a9483c9..6833c2e 100644 --- a/Xcodes/Backend/AppState.swift +++ b/Xcodes/Backend/AppState.swift @@ -127,6 +127,7 @@ class AppState: ObservableObject { } func signIn(username: String, password: String) { + authError = nil signIn(username: username, password: password) .sink( receiveCompletion: { _ in }, diff --git a/Xcodes/Frontend/MainWindow.swift b/Xcodes/Frontend/MainWindow.swift index 4c5aa69..954b221 100644 --- a/Xcodes/Frontend/MainWindow.swift +++ b/Xcodes/Frontend/MainWindow.swift @@ -133,6 +133,7 @@ struct MainWindow: View { .padding() } else { SignInCredentialsView() + .frame(width: 400) } } } diff --git a/Xcodes/Frontend/SignIn/SignInCredentialsView.swift b/Xcodes/Frontend/SignIn/SignInCredentialsView.swift index 06c28ae..593f735 100644 --- a/Xcodes/Frontend/SignIn/SignInCredentialsView.swift +++ b/Xcodes/Frontend/SignIn/SignInCredentialsView.swift @@ -14,30 +14,42 @@ struct SignInCredentialsView: View { Text("Apple ID:") .frame(minWidth: 100, alignment: .trailing) TextField("example@icloud.com", text: $username) - .frame(width: 250) } HStack { Text("Password:") .frame(minWidth: 100, alignment: .trailing) SecureField("Required", text: $password) - .frame(width: 250) + } + if appState.authError != nil { + HStack { + Text("") + .frame(minWidth: 100) + Text(appState.authError?.legibleLocalizedDescription ?? "") + .fixedSize(horizontal: false, vertical: true) + .foregroundColor(.red) + } } HStack { Spacer() - Button("Cancel") { appState.presentedSheet = nil } - .keyboardShortcut(.cancelAction) - ProgressButton(isInProgress: appState.isProcessingAuthRequest, - action: { appState.signIn(username: username, password: password) }) { - Text("Next") + Button("Cancel") { + appState.authError = nil + appState.presentedSheet = nil } + .keyboardShortcut(.cancelAction) + ProgressButton( + isInProgress: appState.isProcessingAuthRequest, + action: { appState.signIn(username: username, password: password) }, + label: { + Text("Next") + } + ) .disabled(username.isEmpty || password.isEmpty) .keyboardShortcut(.defaultAction) } .frame(height: 25) } .padding() - .emittingError($appState.authError, recoveryHandler: { _ in }) } } @@ -45,5 +57,6 @@ struct SignInCredentialsView_Previews: PreviewProvider { static var previews: some View { SignInCredentialsView() .environmentObject(AppState()) + .previewLayout(.sizeThatFits) } } From 761b2bd8cb6ef8ebe3a692cb930cae9fd9ff93ca Mon Sep 17 00:00:00 2001 From: Andrew Erickson Date: Sat, 1 May 2021 09:13:26 -0600 Subject: [PATCH 2/2] handle account locked auth error --- Xcodes/AppleAPI/Sources/AppleAPI/Client.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Xcodes/AppleAPI/Sources/AppleAPI/Client.swift b/Xcodes/AppleAPI/Sources/AppleAPI/Client.swift index f04f069..462286d 100644 --- a/Xcodes/AppleAPI/Sources/AppleAPI/Client.swift +++ b/Xcodes/AppleAPI/Sources/AppleAPI/Client.swift @@ -36,6 +36,10 @@ public class Client { case 401: return Fail(error: AuthenticationError.invalidUsernameOrPassword(username: accountName)) .eraseToAnyPublisher() + case 403: + let errorMessage = responseBody.serviceErrors?.first?.description.replacingOccurrences(of: "-20209: ", with: "") ?? "" + return Fail(error: AuthenticationError.accountLocked(errorMessage)) + .eraseToAnyPublisher() case 409: return self.handleTwoStepOrFactor(data: data, response: response, serviceKey: serviceKey) case 412 where Client.authTypes.contains(responseBody.authType ?? ""): @@ -180,6 +184,7 @@ public enum AuthenticationError: Swift.Error, LocalizedError, Equatable { case appleIDAndPrivacyAcknowledgementRequired case accountUsesTwoStepAuthentication case accountUsesUnknownAuthenticationKind(String?) + case accountLocked(String) case badStatusCode(statusCode: Int, data: Data, response: HTTPURLResponse) public var errorDescription: String? { @@ -203,6 +208,8 @@ public enum AuthenticationError: Swift.Error, LocalizedError, Equatable { return "Received a response from Apple that indicates this account has two-step authentication enabled. xcodes currently only supports the newer two-factor authentication, though. Please consider upgrading to two-factor authentication, or explain why this isn't an option for you by making a new feature request in the Help menu." case .accountUsesUnknownAuthenticationKind: return "Received a response from Apple that indicates this account has two-step or two-factor authentication enabled, but xcodes is unsure how to handle this response. If you continue to have problems, please submit a bug report in the Help menu." + case let .accountLocked(message): + return message case let .badStatusCode(statusCode, _, _): return "Received an unexpected status code: \(statusCode). If you continue to have problems, please submit a bug report in the Help menu." }