mirror of
https://github.com/mas-cli/mas
synced 2024-11-24 12:33:08 +00:00
Improve Account
, SignIn
, SignOut
& ISStoreAccount
extension & associated code.
Prevent `ISAccountService.signIn(with:)` deprecation warning. Improve macOS version handling encapsulation. Output error if `StoreAccount.signin(…)` provides a `nil` `ISStoreAccount`. Improve `signin` `"Already Signed In" error output. Remove unnecessary output. Simplify code. Partial #562 Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
This commit is contained in:
parent
622a154fb9
commit
8e671f2624
7 changed files with 68 additions and 81 deletions
|
@ -163,7 +163,6 @@ To sign into the Mac App Store for the first time run `mas signin`.
|
|||
|
||||
```bash
|
||||
$ mas signin mas@example.com
|
||||
==> Signing in to Apple ID: mas@example.com
|
||||
Password:
|
||||
```
|
||||
|
||||
|
@ -171,15 +170,13 @@ If you experience issues signing in this way, you can ask to sign in using a gra
|
|||
(provided by Mac App Store application):
|
||||
|
||||
```bash
|
||||
$ mas signin --dialog mas@example.com
|
||||
==> Signing in to Apple ID: mas@example.com
|
||||
mas signin --dialog mas@example.com
|
||||
```
|
||||
|
||||
You can also embed your password in the command.
|
||||
|
||||
```bash
|
||||
$ mas signin mas@example.com 'ZdkM4f$gzF;gX3ABXNLf8KcCt.x.np'
|
||||
==> Signing in to Apple ID: mas@example.com
|
||||
mas signin mas@example.com 'ZdkM4f$gzF;gX3ABXNLf8KcCt.x.np'
|
||||
```
|
||||
|
||||
Use `mas signout` to sign out from the Mac App Store.
|
||||
|
|
|
@ -17,65 +17,73 @@ extension ISStoreAccount: StoreAccount {
|
|||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
|
||||
let accountService: ISAccountService = ISServiceProxy.genericShared().accountService
|
||||
accountService.primaryAccount { (storeAccount: ISStoreAccount) in
|
||||
ISServiceProxy.genericShared().accountService.primaryAccount { storeAccount in
|
||||
account = storeAccount
|
||||
group.leave()
|
||||
}
|
||||
|
||||
_ = group.wait(timeout: .now() + 30)
|
||||
} else {
|
||||
// macOS 10.9-10.12
|
||||
let accountStore = CKAccountStore.shared()
|
||||
account = accountStore.primaryAccount
|
||||
account = CKAccountStore.shared().primaryAccount
|
||||
}
|
||||
|
||||
return account
|
||||
}
|
||||
|
||||
static func signIn(username: String, password: String, systemDialog: Bool = false) throws -> StoreAccount {
|
||||
var storeAccount: ISStoreAccount?
|
||||
var maserror: MASError?
|
||||
|
||||
let accountService: ISAccountService = ISServiceProxy.genericShared().accountService
|
||||
let client = ISStoreClient(storeClientType: 0)
|
||||
accountService.setStoreClient(client)
|
||||
|
||||
let context = ISAuthenticationContext(accountID: 0)
|
||||
context.appleIDOverride = username
|
||||
|
||||
if systemDialog {
|
||||
context.appleIDOverride = username
|
||||
if #available(macOS 10.13, *) {
|
||||
// Signing in is no longer possible as of High Sierra.
|
||||
// https://github.com/mas-cli/mas/issues/164
|
||||
throw MASError.notSupported
|
||||
} else {
|
||||
context.demoMode = true
|
||||
context.demoAccountName = username
|
||||
context.demoAccountPassword = password
|
||||
context.demoAutologinMode = true
|
||||
}
|
||||
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
|
||||
// Only works on macOS Sierra and below
|
||||
accountService.signIn(with: context) { success, account, error in
|
||||
if success {
|
||||
storeAccount = account
|
||||
} else {
|
||||
maserror = .signInFailed(error: error as NSError?)
|
||||
let primaryAccount = primaryAccount
|
||||
if primaryAccount != nil {
|
||||
throw MASError.alreadySignedIn(asAccountId: primaryAccount!.identifier)
|
||||
}
|
||||
group.leave()
|
||||
}
|
||||
|
||||
if systemDialog {
|
||||
group.wait()
|
||||
} else {
|
||||
_ = group.wait(timeout: .now() + 30)
|
||||
}
|
||||
let password =
|
||||
password.isEmpty && !systemDialog
|
||||
? String(validatingUTF8: getpass("Password: "))!
|
||||
: password
|
||||
|
||||
if let account = storeAccount {
|
||||
return account
|
||||
}
|
||||
let accountService = ISServiceProxy.genericShared().accountService
|
||||
accountService.setStoreClient(ISStoreClient(storeClientType: 0))
|
||||
|
||||
throw maserror ?? MASError.signInFailed(error: nil)
|
||||
let context = ISAuthenticationContext(accountID: 0)
|
||||
context.appleIDOverride = username
|
||||
if !systemDialog {
|
||||
context.demoMode = true
|
||||
context.demoAccountName = username
|
||||
context.demoAccountPassword = password
|
||||
context.demoAutologinMode = true
|
||||
}
|
||||
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
|
||||
var storeAccount: ISStoreAccount?
|
||||
var maserror: MASError?
|
||||
// Only works on macOS Sierra and below
|
||||
accountService.signIn(with: context) { success, account, error in
|
||||
if success, let account {
|
||||
storeAccount = account
|
||||
} else {
|
||||
maserror = .signInFailed(error: error as NSError?)
|
||||
}
|
||||
group.leave()
|
||||
}
|
||||
|
||||
if systemDialog {
|
||||
group.wait()
|
||||
} else {
|
||||
_ = group.wait(timeout: .now() + 30)
|
||||
}
|
||||
|
||||
if let storeAccount {
|
||||
return storeAccount
|
||||
}
|
||||
|
||||
throw maserror ?? MASError.signInFailed(error: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,8 @@ public struct AccountCommand: CommandProtocol {
|
|||
}
|
||||
|
||||
if let account = ISStoreAccount.primaryAccount {
|
||||
print(String(describing: account.identifier))
|
||||
print(account.identifier)
|
||||
} else {
|
||||
printError("Not signed in")
|
||||
return .failure(.notSignedIn)
|
||||
}
|
||||
return .success(())
|
||||
|
|
|
@ -19,32 +19,16 @@ public struct SignInCommand: CommandProtocol {
|
|||
|
||||
/// Runs the command.
|
||||
public func run(_ options: Options) -> Result<Void, MASError> {
|
||||
if #available(macOS 10.13, *) {
|
||||
// Signing in is no longer possible as of High Sierra.
|
||||
// https://github.com/mas-cli/mas/issues/164
|
||||
return .failure(.notSupported)
|
||||
}
|
||||
|
||||
guard ISStoreAccount.primaryAccount == nil else {
|
||||
return .failure(.alreadySignedIn)
|
||||
}
|
||||
|
||||
do {
|
||||
printInfo("Signing in to Apple ID: \(options.username)")
|
||||
|
||||
let password: String = {
|
||||
if options.password.isEmpty, !options.dialog {
|
||||
return String(validatingUTF8: getpass("Password: "))!
|
||||
}
|
||||
return options.password
|
||||
}()
|
||||
|
||||
_ = try ISStoreAccount.signIn(username: options.username, password: password, systemDialog: options.dialog)
|
||||
} catch let error as NSError {
|
||||
return .failure(.signInFailed(error: error))
|
||||
_ = try ISStoreAccount.signIn(
|
||||
username: options.username,
|
||||
password: options.password,
|
||||
systemDialog: options.dialog
|
||||
)
|
||||
return .success(())
|
||||
} catch {
|
||||
return .failure(error as? MASError ?? .signInFailed(error: error as NSError))
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,7 @@ public struct SignOutCommand: CommandProtocol {
|
|||
/// Runs the command.
|
||||
public func run(_: Options) -> Result<Void, MASError> {
|
||||
if #available(macOS 10.13, *) {
|
||||
let accountService: ISAccountService = ISServiceProxy.genericShared().accountService
|
||||
accountService.signOut()
|
||||
ISServiceProxy.genericShared().accountService.signOut()
|
||||
} else {
|
||||
// Using CKAccountStore to sign out does nothing on High Sierra
|
||||
// https://github.com/mas-cli/mas/issues/129
|
||||
|
|
|
@ -13,7 +13,7 @@ public enum MASError: Error, Equatable {
|
|||
|
||||
case notSignedIn
|
||||
case signInFailed(error: NSError?)
|
||||
case alreadySignedIn
|
||||
case alreadySignedIn(asAccountId: String)
|
||||
|
||||
case purchaseFailed(error: NSError?)
|
||||
case downloadFailed(error: NSError?)
|
||||
|
@ -52,8 +52,8 @@ extension MASError: CustomStringConvertible {
|
|||
return "Sign in failed"
|
||||
}
|
||||
|
||||
case .alreadySignedIn:
|
||||
return "Already signed in"
|
||||
case .alreadySignedIn(let accountId):
|
||||
return "Already signed in as \(accountId)"
|
||||
|
||||
case .purchaseFailed(let error):
|
||||
if let error {
|
||||
|
|
|
@ -57,8 +57,8 @@ class MASErrorTestCase: XCTestCase {
|
|||
}
|
||||
|
||||
func testAlreadySignedIn() {
|
||||
error = .alreadySignedIn
|
||||
XCTAssertEqual(error.description, "Already signed in")
|
||||
error = .alreadySignedIn(asAccountId: "person@example.com")
|
||||
XCTAssertEqual(error.description, "Already signed in as person@example.com")
|
||||
}
|
||||
|
||||
func testPurchaseFailed() {
|
||||
|
|
Loading…
Reference in a new issue