diff --git a/ims/get_admin_organizations.go b/ims/get_admin_organizations.go new file mode 100644 index 0000000..f78b157 --- /dev/null +++ b/ims/get_admin_organizations.go @@ -0,0 +1,89 @@ +// Copyright 2024 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may obtain a copy +// of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +// OF ANY KIND, either express or implied. See the License for the specific language +// governing permissions and limitations under the License. + +package ims + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// GetAdminOrganizationsRequest is the request for GetOrganizations. +type GetAdminOrganizationsRequest struct { + Guid string + AuthSrc string + ServiceToken string + ApiVersion string + ClientID string +} + +// GetAdminOrganizationsResponse is the response for GetOrganizations. +type GetAdminOrganizationsResponse struct { + Response +} + +// GetAdminOrganizationsWithContext reads the user organizations associated to a +// given access token. It returns a non-nil response on success or an error on +// failure. +func (c *Client) GetAdminOrganizationsWithContext(ctx context.Context, r *GetAdminOrganizationsRequest) (*GetAdminOrganizationsResponse, error) { + if r.ApiVersion == "" { + r.ApiVersion = "v5" + } + if r.Guid == "" { + return nil, fmt.Errorf("missing guid") + } + if r.AuthSrc == "" { + return nil, fmt.Errorf("missing auth_src") + } + if r.ServiceToken == "" { + return nil, fmt.Errorf("missing service token") + } + if r.ClientID == "" { + return nil, fmt.Errorf("missing client ID") + } + + data := url.Values{} + data.Set("guid", r.Guid) + data.Set("auth_src", r.AuthSrc) + + req, err := http.NewRequestWithContext(ctx, + http.MethodPost, + fmt.Sprintf("%s/ims/admin_organizations/%s", c.url, r.ApiVersion), + strings.NewReader(data.Encode())) + if err != nil { + return nil, fmt.Errorf("create request: %v", err) + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", r.ServiceToken)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("X-IMS-ClientId", r.ClientID) + + res, err := c.do(req) + if err != nil { + return nil, fmt.Errorf("perform request: %v", err) + } + + if res.StatusCode != http.StatusOK { + return nil, errorResponse(res) + } + + return &GetAdminOrganizationsResponse{ + Response: *res, + }, nil +} + +// GetAdminOrganizations is equivalent to GetAdminOrganizationsWithContext with a +// background context. +func (c *Client) GetAdminOrganizations(r *GetAdminOrganizationsRequest) (*GetAdminOrganizationsResponse, error) { + return c.GetAdminOrganizationsWithContext(context.Background(), r) +} diff --git a/ims/get_admin_organizations_test.go b/ims/get_admin_organizations_test.go new file mode 100644 index 0000000..e9bff51 --- /dev/null +++ b/ims/get_admin_organizations_test.go @@ -0,0 +1,106 @@ +// Copyright 2021 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may obtain a copy +// of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +// OF ANY KIND, either express or implied. See the License for the specific language +// governing permissions and limitations under the License. + +package ims_test + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/adobe/ims-go/ims" +) + +func TestGetAdminOrganizations(t *testing.T) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Fatalf("invalid method: %v", r.Method) + } + if v := r.Header.Get("authorization"); v != "Bearer serviceToken" { + t.Fatalf("invalid authorization header: %v", v) + } + if v := r.Header.Get("X-IMS-clientId"); v != "testClientID" { + t.Fatalf("invalid client ID header: %v", v) + } + + // Check the request body + if err := r.ParseForm(); err != nil { + t.Fatalf("parse form error: %v", err) + } + + guid := r.FormValue("guid") + if guid != "1234567890" { + t.Fatalf("invalid guid: %v", guid) + } + + authSrc := r.FormValue("auth_src") + if authSrc != "TestAuthSrc" { + t.Fatalf("invalid auth_src: %v", authSrc) + } + + _, err := fmt.Fprint(w, `{"foo":"bar"}`) + if err != nil { + t.Fatalf("error writing response: %v", err) + } + })) + defer s.Close() + + c, err := ims.NewClient(&ims.ClientConfig{ + URL: s.URL, + }) + if err != nil { + t.Fatalf("create client: %v", err) + } + + res, err := c.GetAdminOrganizations(&ims.GetAdminOrganizationsRequest{ + Guid: "1234567890", + AuthSrc: "TestAuthSrc", + ServiceToken: "serviceToken", + ClientID: "testClientID", + }) + if err != nil { + t.Fatalf("get admin organizations: %v", err) + } + + if body := string(res.Body); body != `{"foo":"bar"}` { + t.Fatalf("invalid body: %v", body) + } +} + +func TestGetAdminOrganizationsEmptyErrorResponse(t *testing.T) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + defer s.Close() + + c, err := ims.NewClient(&ims.ClientConfig{ + URL: s.URL, + }) + if err != nil { + t.Fatalf("create client: %v", err) + } + + res, err := c.GetAdminOrganizations(&ims.GetAdminOrganizationsRequest{ + Guid: "1234567890", + AuthSrc: "TestAuthSrc", + ServiceToken: "serviceToken", + ClientID: "testClientID", + }) + if res != nil { + t.Fatalf("non-nil response returned") + } + if err == nil { + t.Fatalf("nil error returned") + } + if _, ok := ims.IsError(err); !ok { + t.Fatalf("invalid error type: %v", err) + } +} diff --git a/ims/get_admin_profile.go b/ims/get_admin_profile.go new file mode 100644 index 0000000..c1b4f0c --- /dev/null +++ b/ims/get_admin_profile.go @@ -0,0 +1,87 @@ +// Copyright 2019 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may obtain a copy +// of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +// OF ANY KIND, either express or implied. See the License for the specific language +// governing permissions and limitations under the License. + +package ims + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// GetAdminProfileRequest is the request for GetProfile. +type GetAdminProfileRequest struct { + Guid string + AuthSrc string + ServiceToken string + ApiVersion string + ClientID string +} + +// GetAdminProfileResponse is the response for GetProfile. +type GetAdminProfileResponse struct { + Response +} + +// GetAdminProfileWithContext reads the user profile associated to a given access +// token. It returns a non-nil response on success or an error on failure. +func (c *Client) GetAdminProfileWithContext(ctx context.Context, r *GetAdminProfileRequest) (*GetAdminProfileResponse, error) { + if r.ApiVersion == "" { + r.ApiVersion = "v1" + } + if r.Guid == "" { + return nil, fmt.Errorf("missing guid") + } + if r.AuthSrc == "" { + return nil, fmt.Errorf("missing auth_src") + } + if r.ServiceToken == "" { + return nil, fmt.Errorf("missing service token") + } + if r.ClientID == "" { + return nil, fmt.Errorf("missing client ID") + } + + data := url.Values{} + data.Set("guid", r.Guid) + data.Set("auth_src", r.AuthSrc) + + req, err := http.NewRequestWithContext(ctx, + http.MethodPost, + fmt.Sprintf("%s/ims/admin_profile/%s", c.url, r.ApiVersion), + strings.NewReader(data.Encode())) + if err != nil { + return nil, fmt.Errorf("create request: %v", err) + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", r.ServiceToken)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("X-IMS-ClientID", r.ClientID) + + res, err := c.do(req) + if err != nil { + return nil, fmt.Errorf("perform request: %v", err) + } + + if res.StatusCode != http.StatusOK { + return nil, errorResponse(res) + } + + return &GetAdminProfileResponse{ + Response: *res, + }, nil +} + +// GetAdminProfile is equivalent to GetAdminProfileWithContext with a background context. +func (c *Client) GetAdminProfile(r *GetAdminProfileRequest) (*GetAdminProfileResponse, error) { + return c.GetAdminProfileWithContext(context.Background(), r) +} diff --git a/ims/get_admin_profile_test.go b/ims/get_admin_profile_test.go new file mode 100644 index 0000000..d1d5702 --- /dev/null +++ b/ims/get_admin_profile_test.go @@ -0,0 +1,161 @@ +// Copyright 2021 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may obtain a copy +// of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +// OF ANY KIND, either express or implied. See the License for the specific language +// governing permissions and limitations under the License. + +package ims_test + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/adobe/ims-go/ims" +) + +func TestGetAdminProfile(t *testing.T) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Fatalf("invalid method: %v", r.Method) + } + if v := r.Header.Get("authorization"); v != "Bearer serviceToken" { + t.Fatalf("invalid authorization header: %v", v) + } + if v := r.Header.Get("X-IMS-clientId"); v != "testClientID" { + t.Fatalf("invalid client ID header: %v", v) + } + + // Check the request body + if err := r.ParseForm(); err != nil { + t.Fatalf("parse form error: %v", err) + } + + guid := r.FormValue("guid") + if guid != "1234567890" { + t.Fatalf("invalid guid: %v", guid) + } + + authSrc := r.FormValue("auth_src") + if authSrc != "TestAuthSrc" { + t.Fatalf("invalid auth_src: %v", authSrc) + } + + fmt.Fprint(w, `{"foo":"bar"}`) + })) + defer s.Close() + + c, err := ims.NewClient(&ims.ClientConfig{ + URL: s.URL, + }) + if err != nil { + t.Fatalf("create client: %v", err) + } + + res, err := c.GetAdminProfile(&ims.GetAdminProfileRequest{ + Guid: "1234567890", + AuthSrc: "TestAuthSrc", + ServiceToken: "serviceToken", + ClientID: "testClientID", + }) + if err != nil { + t.Fatalf("get profile: %v", err) + } + + if body := string(res.Body); body != `{"foo":"bar"}` { + t.Fatalf("invalid body: %v", body) + } +} + +func TestGetAdminProfileEmptyErrorResponse(t *testing.T) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + defer s.Close() + + c, err := ims.NewClient(&ims.ClientConfig{ + URL: s.URL, + }) + if err != nil { + t.Fatalf("create client: %v", err) + } + + res, err := c.GetAdminProfile(&ims.GetAdminProfileRequest{ + Guid: "1234567890", + AuthSrc: "TestAuthSrc", + ServiceToken: "serviceToken", + ClientID: "testClientID", + }) + if res != nil { + t.Fatalf("non-nil response returned") + } + if err == nil { + t.Fatalf("nil error returned") + } + if _, ok := ims.IsError(err); !ok { + t.Fatalf("invalid error type: %v", err) + } +} + +func TestGetAdminProfileTooManyRequests(t *testing.T) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Fatalf("invalid method: %v", r.Method) + } + if v := r.Header.Get("authorization"); v != "Bearer serviceToken" { + t.Fatalf("invalid authorization header: %v", v) + } + if v := r.Header.Get("X-IMS-clientId"); v != "testClientID" { + t.Fatalf("invalid client ID header: %v", v) + } + + w.Header().Set("Retry-After", "77") + w.Header().Set("x-debug-id", "banana") + w.WriteHeader(http.StatusTooManyRequests) + })) + defer s.Close() + + c, err := ims.NewClient(&ims.ClientConfig{ + URL: s.URL, + }) + if err != nil { + t.Fatalf("create client: %v", err) + } + + res, err := c.GetAdminProfile(&ims.GetAdminProfileRequest{ + Guid: "1234567890", + AuthSrc: "TestAuthSrc", + ServiceToken: "serviceToken", + ClientID: "testClientID", + }) + + if err == nil { + t.Fatalf("expected error in get profile") + } + + if res != nil { + t.Fatalf("expected nil response because of error") + } + + imsErr, ok := ims.IsError(err) + if !ok { + t.Fatalf("expected IMS error") + } + + if imsErr.StatusCode != http.StatusTooManyRequests { + t.Fatalf("invalid status code: %v", imsErr.StatusCode) + } + + if imsErr.RetryAfter != "77" { + t.Fatalf("invalid retry-after header: %v", imsErr.RetryAfter) + } + + if imsErr.XDebugID != "banana" { + t.Fatalf("invalid x-debug-id header: %v", imsErr.XDebugID) + } +}