Skip to content
Open
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
15 changes: 12 additions & 3 deletions pkg/appstore/appstore_bag.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,30 @@ func (t *appstore) Bag(input BagInput) (BagOutput, error) {
}

return BagOutput{
AuthEndpoint: res.Data.URLBag.AuthEndpoint,
AuthEndpoint: res.Data.AuthEndpoint(),
}, nil
}

type bagResult struct {
URLBag urlBag `plist:"urlBag,omitempty"`
AuthenticateAccount string `plist:"authenticateAccount,omitempty"`
URLBag urlBag `plist:"urlBag,omitempty"`
}

type urlBag struct {
AuthEndpoint string `plist:"authenticateAccount,omitempty"`
}

func (r bagResult) AuthEndpoint() string {
if r.AuthenticateAccount != "" {
return r.AuthenticateAccount
}

return r.URLBag.AuthEndpoint
}

func (*appstore) bagRequest(guid string) http.Request {
return http.Request{
URL: fmt.Sprintf("https://%s%s?guid=%s", PrivateInitDomain, PrivateInitPath, guid),
URL: fmt.Sprintf("https://%s%s?ix=6&guid=%s", PrivateInitDomain, PrivateInitPath, guid),
Method: http.MethodGET,
ResponseFormat: http.ResponseFormatXML,
Headers: map[string]string{
Expand Down
27 changes: 26 additions & 1 deletion pkg/appstore/appstore_bag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ var _ = Describe("AppStore (Bag)", func() {
Send(gomock.Any()).
Do(func(req http.Request) {
Expect(req.Method).To(Equal(http.MethodGET))
Expect(req.URL).To(Equal("https://init.itunes.apple.com/bag.xml?guid=AABBCCDDEEFF"))
Expect(req.URL).To(Equal("https://init.itunes.apple.com/bag.xml?ix=6&guid=AABBCCDDEEFF"))
Expect(req.ResponseFormat).To(Equal(http.ResponseFormatXML))
Expect(req.Headers).To(HaveKeyWithValue("Accept", "application/xml"))
}).
Expand All @@ -118,6 +118,31 @@ var _ = Describe("AppStore (Bag)", func() {
})
})

When("request is successful with authenticateAccount in root", func() {
const testAuthEndpoint = "https://example.com"

BeforeEach(func() {
mockMachine.EXPECT().
MacAddress().
Return("aa:bb:cc:dd:ee:ff", nil)

mockBagClient.EXPECT().
Send(gomock.Any()).
Return(http.Result[bagResult]{
StatusCode: gohttp.StatusOK,
Data: bagResult{
AuthenticateAccount: testAuthEndpoint,
},
}, nil)
})

It("returns output", func() {
out, err := as.Bag(BagInput{})
Expect(err).ToNot(HaveOccurred())
Expect(out.AuthEndpoint).To(Equal(testAuthEndpoint))
})
})

When("request is successful but authenticateAccount is empty", func() {
BeforeEach(func() {
mockMachine.EXPECT().
Expand Down
17 changes: 16 additions & 1 deletion pkg/appstore/appstore_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type loginResult struct {

func (t *appstore) login(email, password, authCode, guid, endpoint string) (Account, error) {
redirect := ""

fastEndpoint := strings.Replace(endpoint, "/auth/v1/native", "/auth/v1/native/fast/", 1)
var (
err error
res http.Result[loginResult]
Expand All @@ -83,6 +83,13 @@ func (t *appstore) login(email, password, authCode, guid, endpoint string) (Acco
}

if retry, redirect, err = t.parseLoginResponse(&res, attempt, authCode); err != nil {
if authCode != "" && endpoint != fastEndpoint && missingLoginCredentials(res.Data) {
endpoint = fastEndpoint
redirect = ""
retry = true
err = nil
continue
}
return Account{}, err
}
}
Expand Down Expand Up @@ -150,13 +157,21 @@ func (t *appstore) parseLoginResponse(res *http.Result[loginResult], attempt int
} else {
err = NewErrorWithMetadata(errors.New("something went wrong"), res)
}
} else if (res.StatusCode == gohttp.StatusOK || res.StatusCode == gohttp.StatusNoContent) && authCode == "" && missingLoginCredentials(res.Data) {
err = ErrAuthCodeRequired
} else if (res.StatusCode == gohttp.StatusOK || res.StatusCode == gohttp.StatusNoContent) && missingLoginCredentials(res.Data) {
err = NewErrorWithMetadata(errors.New("login response is missing password token and directory services id"), res)
} else if res.StatusCode != gohttp.StatusOK || res.Data.PasswordToken == "" || res.Data.DirectoryServicesID == "" {
err = NewErrorWithMetadata(errors.New("something went wrong"), res)
}

return retry, redirect, err
}

func missingLoginCredentials(data loginResult) bool {
return data.PasswordToken == "" && data.DirectoryServicesID == ""
}

func (t *appstore) loginRequest(email, password, authCode, guid, endpoint string, attempt int) http.Request {
return http.Request{
Method: http.MethodPOST,
Expand Down