Skip to content
Merged
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
2 changes: 1 addition & 1 deletion apiintegrations/msgraph/msgraph_api_exceptions.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// msgraph_api_exceptions.go
// apiintegrations/msgraph/msgraph_api_exceptions.go
package msgraph

import (
Expand Down
2 changes: 1 addition & 1 deletion apiintegrations/msgraph/msgraph_api_handler.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// msgraph_api_handler.go
// apiintegrations/msgraph/msgraph_api_handler.go
package msgraph

import "github.com/deploymenttheory/go-api-http-client/logger"
Expand Down
2 changes: 1 addition & 1 deletion apiintegrations/msgraph/msgraph_api_handler_constants.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// msgraph_api_handler_constants.go
// apiintegrations/msgraph/msgraph_api_handler_constants.go
package msgraph

// Endpoint constants represent the URL suffixes used for graph API token interactions.
Expand Down
2 changes: 1 addition & 1 deletion apiintegrations/msgraph/msgraph_api_headers.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// msgraph_api_headers.go
// apiintegrations/msgraph/msgraph_api_headers.go
package msgraph

import (
Expand Down
36 changes: 36 additions & 0 deletions apiintegrations/msgraph/msgraph_api_headers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// apiintegrations/msgraph/msgraph_api_headers_test.go
package msgraph

import (
"testing"

"github.com/deploymenttheory/go-api-http-client/mocklogger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

// TestGetAPIRequestHeaders tests the GetAPIRequestHeaders function.
func TestGetAPIRequestHeaders(t *testing.T) {
handler := GraphAPIHandler{Logger: mocklogger.NewMockLogger()}
endpoint := "/api/data"
handler.Logger.(*mocklogger.MockLogger).On("Debug", mock.Anything, mock.Anything).Maybe()

expectedHeaders := map[string]string{
"Accept": "application/x-x509-ca-cert;q=0.95,application/pkix-cert;q=0.94,application/pem-certificate-chain;q=0.93,application/octet-stream;q=0.8,image/png;q=0.75,image/jpeg;q=0.74,image/*;q=0.7,application/xml;q=0.65,text/xml;q=0.64,text/xml;charset=UTF-8;q=0.63,application/json;q=0.5,text/html;q=0.5,text/plain;q=0.4,*/*;q=0.05",
"Content-Type": "application/json",
"Authorization": "",
"User-Agent": "go-api-http-client-msgraph-handler",
}

headers := handler.GetAPIRequestHeaders(endpoint)
assert.Equal(t, expectedHeaders, headers)
handler.Logger.(*mocklogger.MockLogger).AssertExpectations(t)
}

// TestGetContentTypeHeader tests the GetContentTypeHeader function.
func TestGetAcceptHeader(t *testing.T) {
handler := GraphAPIHandler{}
acceptHeader := handler.GetAcceptHeader()
expectedHeader := "application/x-x509-ca-cert;q=0.95,application/pkix-cert;q=0.94,application/pem-certificate-chain;q=0.93,application/octet-stream;q=0.8,image/png;q=0.75,image/jpeg;q=0.74,image/*;q=0.7,application/xml;q=0.65,text/xml;q=0.64,text/xml;charset=UTF-8;q=0.63,application/json;q=0.5,text/html;q=0.5,text/plain;q=0.4,*/*;q=0.05"
assert.Equal(t, expectedHeader, acceptHeader, "The Accept header should correctly prioritize MIME types.")
}
46 changes: 10 additions & 36 deletions apiintegrations/msgraph/msgraph_api_request.go
Original file line number Diff line number Diff line change
@@ -1,55 +1,29 @@
// msgraph_api_request.go
// apiintegrations/msgraph/msgraph_api_request.go
package msgraph

import (
"bytes"
"encoding/json"
"encoding/xml"
"io"
"mime/multipart"
"os"
"strings"

"github.com/deploymenttheory/go-api-http-client/logger"
"go.uber.org/zap"
)

// MarshalRequest encodes the request body according to the endpoint for the API.
// MarshalRequest encodes the request body as JSON for the Microsoft Graph API.
func (g *GraphAPIHandler) MarshalRequest(body interface{}, method string, endpoint string, log logger.Logger) ([]byte, error) {
var (
data []byte
err error
)

// Determine the format based on the endpoint
format := "json"
if strings.Contains(endpoint, "/JSSResource") {
format = "xml"
} else if strings.Contains(endpoint, "/api") {
format = "json"
// Marshal the body as JSON
data, err := json.Marshal(body)
if err != nil {
g.Logger.Error("Failed marshaling JSON request", zap.Error(err))

Check warning

Code scanning / gosec

Errors unhandled.

Errors unhandled.
return nil, err
}

switch format {
case "xml":
data, err = xml.Marshal(body)
if err != nil {
return nil, err
}

if method == "POST" || method == "PUT" {
g.Logger.Debug("XML Request Body", zap.String("Body", string(data)))
}

case "json":
data, err = json.Marshal(body)
if err != nil {
g.Logger.Error("Failed marshaling JSON request", zap.Error(err))
return nil, err
}

if method == "POST" || method == "PUT" || method == "PATCH" {
g.Logger.Debug("JSON Request Body", zap.String("Body", string(data)))
}
// Log the JSON request body for POST, PUT, or PATCH methods
if method == "POST" || method == "PUT" || method == "PATCH" {
g.Logger.Debug("JSON Request Body", zap.String("Body", string(data)))
}

return data, nil
Expand Down
101 changes: 101 additions & 0 deletions apiintegrations/msgraph/msgraph_api_request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// apiintegrations/msgraph/msgraph_api_request_test.go
package msgraph

import (
"bytes"
"encoding/json"
"io"
"mime/multipart"
"os"
"path/filepath"
"strings"
"testing"

"github.com/deploymenttheory/go-api-http-client/mocklogger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
)

// TestMarshalRequest tests the MarshalRequest function.
func TestMarshalRequest(t *testing.T) {
body := map[string]interface{}{
"name": "John Doe",
"age": 30,
}
method := "POST"
endpoint := "/users"
mockLog := mocklogger.NewMockLogger()
handler := GraphAPIHandler{Logger: mockLog}

expectedData, _ := json.Marshal(body)

// Correct the way we setup the logger mock
mockLog.On("Debug", "JSON Request Body", mock.MatchedBy(func(fields []zap.Field) bool {
if len(fields) != 1 {
return false
}
return fields[0].Key == "Body" && fields[0].String == string(expectedData)
})).Once()

data, err := handler.MarshalRequest(body, method, endpoint, mockLog)

assert.NoError(t, err)
assert.Equal(t, expectedData, data)
mockLog.AssertExpectations(t)
}

func TestMarshalMultipartRequest(t *testing.T) {
// Prepare the logger mock
mockLog := mocklogger.NewMockLogger()

// Setting up a temporary file to simulate a file upload
tempDir := t.TempDir() // Create a temporary directory for test files
tempFile, err := os.CreateTemp(tempDir, "upload-*.txt")
assert.NoError(t, err)
defer os.Remove(tempFile.Name()) // Ensure the file is removed after the test

_, err = tempFile.WriteString("Test file content")
assert.NoError(t, err)
tempFile.Close()

handler := GraphAPIHandler{Logger: mockLog}

fields := map[string]string{"field1": "value1"}
files := map[string]string{"fileField": tempFile.Name()}

// Execute the function
body, contentType, err := handler.MarshalMultipartRequest(fields, files, mockLog)
assert.NoError(t, err)
assert.Contains(t, contentType, "multipart/form-data; boundary=")

// Check if the multipart form data contains the correct fields and file data
reader := multipart.NewReader(bytes.NewReader(body), strings.TrimPrefix(contentType, "multipart/form-data; boundary="))
var foundField, foundFile bool

for {
part, err := reader.NextPart()
if err == io.EOF {
break
}
assert.NoError(t, err)

if part.FormName() == "field1" {
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(part)
assert.NoError(t, err)
assert.Equal(t, "value1", buf.String())
foundField = true
} else if part.FileName() == filepath.Base(tempFile.Name()) {
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(part)
assert.NoError(t, err)
assert.Equal(t, "Test file content", buf.String())
foundFile = true
}
}

// Ensure all expected parts were found
assert.True(t, foundField, "Text field not found in the multipart form data")
assert.True(t, foundFile, "File not found in the multipart form data")
}
2 changes: 1 addition & 1 deletion apiintegrations/msgraph/msgraph_api_url.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// msgraph_api_url.go
// apiintegrations/msgraph/msgraph_api_url.go
package msgraph

import (
Expand Down
55 changes: 55 additions & 0 deletions apiintegrations/msgraph/msgraph_api_url_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// apiintegrations/msgraph/msgraph_api_url_test.go
package msgraph

import (
"fmt"
"testing"

"github.com/deploymenttheory/go-api-http-client/mocklogger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

// TestConstructAPIResourceEndpoint tests the ConstructAPIResourceEndpoint function.
func TestConstructAPIResourceEndpoint(t *testing.T) {
const baseURL = "https://graph.microsoft.com"
const endpointPath = "/v1.0/users"

// Mock logger
mockLog := mocklogger.NewMockLogger()
mockLog.On("Debug", mock.AnythingOfType("string"), mock.Anything).Once()

handler := GraphAPIHandler{
TenantID: "dummy-tenant-id",
Logger: mockLog,
}

// Set base domain assuming it's being mocked or controlled internally
expectedURL := fmt.Sprintf("%s%s", baseURL, endpointPath)
resultURL := handler.ConstructAPIResourceEndpoint(endpointPath, mockLog)

assert.Equal(t, expectedURL, resultURL, "URL should match expected format")
mockLog.AssertExpectations(t)
}

// TestConstructAPIAuthEndpoint tests the ConstructAPIAuthEndpoint function.
func TestConstructAPIAuthEndpoint(t *testing.T) {
const baseURL = "https://login.microsoftonline.com"
const endpointPath = "/oauth2/v2.0/token"

// Mock logger
mockLog := mocklogger.NewMockLogger()
mockLog.On("Debug", mock.AnythingOfType("string"), mock.Anything).Once()

handler := GraphAPIHandler{
TenantID: "dummy-tenant-id",
Logger: mockLog,
}

// Construct the full URL by combining the base URL, tenant ID, and endpoint path.
expectedURL := fmt.Sprintf("%s/%s%s", baseURL, handler.TenantID, endpointPath)
resultURL := handler.ConstructAPIAuthEndpoint(endpointPath, mockLog)

assert.Equal(t, expectedURL, resultURL, "URL should match expected format")
mockLog.AssertExpectations(t)
}
Loading