Skip to content

Commit ffc7223

Browse files
authored
Merge pull request #129 from RobotsAndPencils/andrew/signInErrorHandling
Show sign in errors inline on sign in view
2 parents 499d33f + 761b2bd commit ffc7223

File tree

4 files changed

+30
-8
lines changed

4 files changed

+30
-8
lines changed

Xcodes/AppleAPI/Sources/AppleAPI/Client.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public class Client {
3636
case 401:
3737
return Fail(error: AuthenticationError.invalidUsernameOrPassword(username: accountName))
3838
.eraseToAnyPublisher()
39+
case 403:
40+
let errorMessage = responseBody.serviceErrors?.first?.description.replacingOccurrences(of: "-20209: ", with: "") ?? ""
41+
return Fail(error: AuthenticationError.accountLocked(errorMessage))
42+
.eraseToAnyPublisher()
3943
case 409:
4044
return self.handleTwoStepOrFactor(data: data, response: response, serviceKey: serviceKey)
4145
case 412 where Client.authTypes.contains(responseBody.authType ?? ""):
@@ -180,6 +184,7 @@ public enum AuthenticationError: Swift.Error, LocalizedError, Equatable {
180184
case appleIDAndPrivacyAcknowledgementRequired
181185
case accountUsesTwoStepAuthentication
182186
case accountUsesUnknownAuthenticationKind(String?)
187+
case accountLocked(String)
183188
case badStatusCode(statusCode: Int, data: Data, response: HTTPURLResponse)
184189

185190
public var errorDescription: String? {
@@ -203,6 +208,8 @@ public enum AuthenticationError: Swift.Error, LocalizedError, Equatable {
203208
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."
204209
case .accountUsesUnknownAuthenticationKind:
205210
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."
211+
case let .accountLocked(message):
212+
return message
206213
case let .badStatusCode(statusCode, _, _):
207214
return "Received an unexpected status code: \(statusCode). If you continue to have problems, please submit a bug report in the Help menu."
208215
}

Xcodes/Backend/AppState.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ class AppState: ObservableObject {
127127
}
128128

129129
func signIn(username: String, password: String) {
130+
authError = nil
130131
signIn(username: username, password: password)
131132
.sink(
132133
receiveCompletion: { _ in },

Xcodes/Frontend/MainWindow.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct MainWindow: View {
133133
.padding()
134134
} else {
135135
SignInCredentialsView()
136+
.frame(width: 400)
136137
}
137138
}
138139
}

Xcodes/Frontend/SignIn/SignInCredentialsView.swift

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,49 @@ struct SignInCredentialsView: View {
1414
Text("Apple ID:")
1515
.frame(minWidth: 100, alignment: .trailing)
1616
TextField("[email protected]", text: $username)
17-
.frame(width: 250)
1817
}
1918
HStack {
2019
Text("Password:")
2120
.frame(minWidth: 100, alignment: .trailing)
2221
SecureField("Required", text: $password)
23-
.frame(width: 250)
22+
}
23+
if appState.authError != nil {
24+
HStack {
25+
Text("")
26+
.frame(minWidth: 100)
27+
Text(appState.authError?.legibleLocalizedDescription ?? "")
28+
.fixedSize(horizontal: false, vertical: true)
29+
.foregroundColor(.red)
30+
}
2431
}
2532

2633
HStack {
2734
Spacer()
28-
Button("Cancel") { appState.presentedSheet = nil }
29-
.keyboardShortcut(.cancelAction)
30-
ProgressButton(isInProgress: appState.isProcessingAuthRequest,
31-
action: { appState.signIn(username: username, password: password) }) {
32-
Text("Next")
35+
Button("Cancel") {
36+
appState.authError = nil
37+
appState.presentedSheet = nil
3338
}
39+
.keyboardShortcut(.cancelAction)
40+
ProgressButton(
41+
isInProgress: appState.isProcessingAuthRequest,
42+
action: { appState.signIn(username: username, password: password) },
43+
label: {
44+
Text("Next")
45+
}
46+
)
3447
.disabled(username.isEmpty || password.isEmpty)
3548
.keyboardShortcut(.defaultAction)
3649
}
3750
.frame(height: 25)
3851
}
3952
.padding()
40-
.emittingError($appState.authError, recoveryHandler: { _ in })
4153
}
4254
}
4355

4456
struct SignInCredentialsView_Previews: PreviewProvider {
4557
static var previews: some View {
4658
SignInCredentialsView()
4759
.environmentObject(AppState())
60+
.previewLayout(.sizeThatFits)
4861
}
4962
}

0 commit comments

Comments
 (0)