diff --git a/api/api_init_test.go b/api/api_init_test.go index c959dd3..b875f57 100644 --- a/api/api_init_test.go +++ b/api/api_init_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "io" "os" @@ -73,7 +74,7 @@ func init() { } client := &gosip.SPClient{AuthCnfg: auth} // Pre-auth for tests not include auth timing involved - if _, _, err := client.AuthCnfg.GetAuth(); err != nil { + if _, _, err := client.AuthCnfg.GetAuth(context.Background()); err != nil { fmt.Printf("can't auth, %s\n", err) // Force all test being skipped in case of auth issues return nil @@ -91,7 +92,7 @@ func init() { } client := &gosip.SPClient{AuthCnfg: auth} // Pre-auth for tests not include auth timing involved - if _, _, err := client.AuthCnfg.GetAuth(); err != nil { + if _, _, err := client.AuthCnfg.GetAuth(context.Background()); err != nil { fmt.Printf("can't auth, %s\n", err) // Force all test being skipped in case of auth issues return nil diff --git a/api/associatedGroups_test.go b/api/associatedGroups_test.go index 764ff43..c8675d3 100644 --- a/api/associatedGroups_test.go +++ b/api/associatedGroups_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -10,7 +11,7 @@ func TestAssociatedGroups(t *testing.T) { sp := NewSP(spClient) t.Run("Visitors", func(t *testing.T) { - group, err := sp.Web().AssociatedGroups().Visitors().Get() + group, err := sp.Web().AssociatedGroups().Visitors().Get(context.Background()) if err != nil { t.Error(err) } @@ -20,7 +21,7 @@ func TestAssociatedGroups(t *testing.T) { }) t.Run("Members", func(t *testing.T) { - group, err := sp.Web().AssociatedGroups().Members().Get() + group, err := sp.Web().AssociatedGroups().Members().Get(context.Background()) if err != nil { t.Error(err) } @@ -30,7 +31,7 @@ func TestAssociatedGroups(t *testing.T) { }) t.Run("Owners", func(t *testing.T) { - group, err := sp.Web().AssociatedGroups().Owners().Get() + group, err := sp.Web().AssociatedGroups().Owners().Get(context.Background()) if err != nil { t.Error(err) } diff --git a/api/attachments.go b/api/attachments.go index 8ea21ae..cbd3709 100644 --- a/api/attachments.go +++ b/api/attachments.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "io" "net/http" @@ -58,16 +59,16 @@ func NewAttachment(client *gosip.SPClient, endpoint string, config *RequestConfi } // Get gets attachments collection response -func (attachments *Attachments) Get() (AttachmentsResp, error) { +func (attachments *Attachments) Get(ctx context.Context) (AttachmentsResp, error) { client := NewHTTPClient(attachments.client) - return client.Get(attachments.endpoint, attachments.config) + return client.Get(ctx, attachments.endpoint, attachments.config) } // Add uploads new attachment to the item -func (attachments *Attachments) Add(name string, content io.Reader) (AttachmentResp, error) { +func (attachments *Attachments) Add(ctx context.Context, name string, content io.Reader) (AttachmentResp, error) { client := NewHTTPClient(attachments.client) endpoint := fmt.Sprintf("%s/Add(FileName='%s')", attachments.endpoint, name) - return client.Post(endpoint, content, attachments.config) + return client.Post(ctx, endpoint, content, attachments.config) } // GetByName gets an attachment by its name @@ -80,31 +81,31 @@ func (attachments *Attachments) GetByName(fileName string) *Attachment { } // Get gets attachment data object -func (attachment *Attachment) Get() (AttachmentResp, error) { +func (attachment *Attachment) Get(ctx context.Context) (AttachmentResp, error) { client := NewHTTPClient(attachment.client) - return client.Get(attachment.endpoint, attachment.config) + return client.Get(ctx, attachment.endpoint, attachment.config) } // Delete delete an attachment skipping recycle bin -func (attachment *Attachment) Delete() error { +func (attachment *Attachment) Delete(ctx context.Context) error { client := NewHTTPClient(attachment.client) - _, err := client.Delete(attachment.endpoint, attachment.config) + _, err := client.Delete(ctx, attachment.endpoint, attachment.config) return err } // Recycle moves an attachment to the recycle bin -func (attachment *Attachment) Recycle() error { +func (attachment *Attachment) Recycle(ctx context.Context) error { client := NewHTTPClient(attachment.client) endpoint := fmt.Sprintf("%s/RecycleObject", attachment.endpoint) - _, err := client.Post(endpoint, nil, attachment.config) + _, err := client.Post(ctx, endpoint, nil, attachment.config) return err } // GetReader gets attachment body data reader -func (attachment *Attachment) GetReader() (io.ReadCloser, error) { +func (attachment *Attachment) GetReader(ctx context.Context) (io.ReadCloser, error) { endpoint := fmt.Sprintf("%s/$value", attachment.endpoint) - req, err := http.NewRequest("GET", endpoint, nil) + req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil) if err != nil { return nil, err } @@ -127,8 +128,8 @@ func (attachment *Attachment) GetReader() (io.ReadCloser, error) { } // Download downloads attachment's as byte array -func (attachment *Attachment) Download() ([]byte, error) { - body, err := attachment.GetReader() +func (attachment *Attachment) Download(ctx context.Context) ([]byte, error) { + body, err := attachment.GetReader(ctx) if err != nil { return nil, err } diff --git a/api/attachments_test.go b/api/attachments_test.go index 4b55407..b0b54d7 100644 --- a/api/attachments_test.go +++ b/api/attachments_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" "github.com/google/uuid" @@ -13,11 +14,11 @@ func TestAttachments(t *testing.T) { web := NewSP(spClient).Web() listTitle := uuid.New().String() - if _, err := web.Lists().Add(listTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), listTitle, nil); err != nil { t.Error(err) } list := web.Lists().GetByTitle(listTitle) - item, err := list.Items().Add([]byte(`{"Title":"Attachment test"}`)) + item, err := list.Items().Add(context.Background(), []byte(`{"Title":"Attachment test"}`)) if err != nil { t.Error(err) } @@ -30,14 +31,14 @@ func TestAttachments(t *testing.T) { "att_04.txt": []byte("attachment 04"), } for fileName, content := range attachments { - if _, err := list.Items().GetByID(item.Data().ID).Attachments().Add(fileName, bytes.NewBuffer(content)); err != nil { + if _, err := list.Items().GetByID(item.Data().ID).Attachments().Add(context.Background(), fileName, bytes.NewBuffer(content)); err != nil { t.Error(err) } } }) t.Run("Get", func(t *testing.T) { - data, err := list.Items().GetByID(item.Data().ID).Attachments().Get() + data, err := list.Items().GetByID(item.Data().ID).Attachments().Get(context.Background()) if err != nil { t.Error(err) } @@ -50,7 +51,7 @@ func TestAttachments(t *testing.T) { }) t.Run("GetByName", func(t *testing.T) { - data, err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_01.txt").Get() + data, err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_01.txt").Get(context.Background()) if err != nil { t.Error(err) } @@ -63,7 +64,7 @@ func TestAttachments(t *testing.T) { }) t.Run("Delete", func(t *testing.T) { - if err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_02.txt").Delete(); err != nil { + if err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_02.txt").Delete(context.Background()); err != nil { t.Error(err) } }) @@ -73,14 +74,14 @@ func TestAttachments(t *testing.T) { t.Skip("is not supported with SP 2013") } - if err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_03.txt").Recycle(); err != nil { + if err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_03.txt").Recycle(context.Background()); err != nil { t.Error(err) } }) t.Run("Download", func(t *testing.T) { expectedContent := []byte("attachment 04") - content, err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_04.txt").Download() + content, err := list.Items().GetByID(item.Data().ID).Attachments().GetByName("att_04.txt").Download(context.Background()) if err != nil { t.Error(err) } @@ -89,7 +90,7 @@ func TestAttachments(t *testing.T) { } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/changes.go b/api/changes.go index 895f944..61936ab 100644 --- a/api/changes.go +++ b/api/changes.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "time" @@ -89,10 +90,10 @@ func NewChanges(client *gosip.SPClient, endpoint string, config *RequestConfig) } // GetCurrentToken gets current change token for this parent entity -func (changes *Changes) GetCurrentToken() (string, error) { +func (changes *Changes) GetCurrentToken(ctx context.Context) (string, error) { endpoint := fmt.Sprintf("%s?$select=CurrentChangeToken", changes.endpoint) client := NewHTTPClient(changes.client) - data, err := client.Get(endpoint, changes.config) + data, err := client.Get(ctx, endpoint, changes.config) if err != nil { return "", err } @@ -107,7 +108,7 @@ func (changes *Changes) GetCurrentToken() (string, error) { } // GetChanges gets changes in scope of the parent container using provided change query -func (changes *Changes) GetChanges(changeQuery *ChangeQuery) (*ChangesResp, error) { +func (changes *Changes) GetChanges(ctx context.Context, changeQuery *ChangeQuery) (*ChangesResp, error) { endpoint := toURL(fmt.Sprintf("%s/GetChanges", changes.endpoint), changes.modifiers) client := NewHTTPClient(changes.client) metadata := map[string]interface{}{} @@ -132,7 +133,7 @@ func (changes *Changes) GetChanges(changeQuery *ChangeQuery) (*ChangesResp, erro if err != nil { return nil, err } - data, err := client.Post(endpoint, bytes.NewBuffer(body), changes.config) + data, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), changes.config) if err != nil { return nil, err } @@ -159,7 +160,7 @@ func (changes *Changes) GetChanges(changeQuery *ChangeQuery) (*ChangesResp, erro return nil, fmt.Errorf("can't get next page of an empty collection") } changeQuery.ChangeTokenStart = result.data[len(result.data)-1].ChangeToken.StringValue - return changes.GetChanges(changeQuery) + return changes.GetChanges(ctx, changeQuery) } return result, nil diff --git a/api/changes_test.go b/api/changes_test.go index 9f06a1f..a44dc16 100644 --- a/api/changes_test.go +++ b/api/changes_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "testing" @@ -13,13 +14,13 @@ func TestChanges(t *testing.T) { sp := NewSP(spClient) listTitle := uuid.New().String() - if _, err := sp.Web().Lists().Add(listTitle, nil); err != nil { + if _, err := sp.Web().Lists().Add(context.Background(), listTitle, nil); err != nil { t.Error(err) } list := sp.Web().Lists().GetByTitle(listTitle) t.Run("GetCurrentToken", func(t *testing.T) { - token, err := sp.Web().Changes().Conf(headers.verbose).GetCurrentToken() + token, err := sp.Web().Changes().Conf(headers.verbose).GetCurrentToken(context.Background()) if err != nil { t.Error(err) } @@ -28,14 +29,14 @@ func TestChanges(t *testing.T) { } if envCode != "2013" { - token, err := sp.Web().Changes().Conf(headers.minimalmetadata).GetCurrentToken() + token, err := sp.Web().Changes().Conf(headers.minimalmetadata).GetCurrentToken(context.Background()) if err != nil { t.Error(err) } if token == "" { t.Error("empty change token") } - token, err = sp.Web().Changes().Conf(headers.nometadata).GetCurrentToken() + token, err = sp.Web().Changes().Conf(headers.nometadata).GetCurrentToken(context.Background()) if err != nil { t.Error(err) } @@ -46,17 +47,17 @@ func TestChanges(t *testing.T) { }) t.Run("ListChanges", func(t *testing.T) { - token, err := list.Changes().GetCurrentToken() + token, err := list.Changes().GetCurrentToken(context.Background()) if err != nil { t.Error(err) } if token == "" { t.Error("empty change token") } - if _, err := list.Items().Add([]byte(`{"Title":"Another item"}`)); err != nil { + if _, err := list.Items().Add(context.Background(), []byte(`{"Title":"Another item"}`)); err != nil { t.Error(err) } - changes, err := list.Changes().GetChanges(&ChangeQuery{ + changes, err := list.Changes().GetChanges(context.Background(), &ChangeQuery{ ChangeTokenStart: token, List: true, Item: true, @@ -71,17 +72,17 @@ func TestChanges(t *testing.T) { }) t.Run("WebChanges", func(t *testing.T) { - token, err := sp.Web().Changes().GetCurrentToken() + token, err := sp.Web().Changes().GetCurrentToken(context.Background()) if err != nil { t.Error(err) } if token == "" { t.Error("empty change token") } - if _, err := list.Items().Add([]byte(`{"Title":"New item"}`)); err != nil { + if _, err := list.Items().Add(context.Background(), []byte(`{"Title":"New item"}`)); err != nil { t.Error(err) } - changes, err := sp.Web().Changes().GetChanges(&ChangeQuery{ + changes, err := sp.Web().Changes().GetChanges(context.Background(), &ChangeQuery{ ChangeTokenStart: token, Web: true, Item: true, @@ -96,17 +97,17 @@ func TestChanges(t *testing.T) { }) t.Run("SiteChanges", func(t *testing.T) { - token, err := sp.Site().Changes().GetCurrentToken() + token, err := sp.Site().Changes().GetCurrentToken(context.Background()) if err != nil { t.Error(err) } if token == "" { t.Error("empty change token") } - if _, err := list.Items().Add([]byte(`{"Title":"New item"}`)); err != nil { + if _, err := list.Items().Add(context.Background(), []byte(`{"Title":"New item"}`)); err != nil { t.Error(err) } - changes, err := sp.Site().Changes().GetChanges(&ChangeQuery{ + changes, err := sp.Site().Changes().GetChanges(context.Background(), &ChangeQuery{ ChangeTokenStart: token, Site: true, Item: true, @@ -134,7 +135,7 @@ func TestChanges(t *testing.T) { } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } } @@ -145,13 +146,13 @@ func TestChangesPagination(t *testing.T) { sp := NewSP(spClient) listTitle := uuid.New().String() - if _, err := sp.Web().Lists().Add(listTitle, nil); err != nil { + if _, err := sp.Web().Lists().Add(context.Background(), listTitle, nil); err != nil { t.Error(err) } list := sp.Web().Lists().GetByTitle(listTitle) t.Run("ListChanges", func(t *testing.T) { - token, err := list.Changes().GetCurrentToken() + token, err := list.Changes().GetCurrentToken(context.Background()) if err != nil { t.Error(err) } @@ -159,11 +160,11 @@ func TestChangesPagination(t *testing.T) { t.Error("empty change token") } for i := 1; i <= 5; i++ { - if _, err := list.Items().Add([]byte(fmt.Sprintf(`{"Title":"Item %d"}`, i))); err != nil { + if _, err := list.Items().Add(context.Background(), []byte(fmt.Sprintf(`{"Title":"Item %d"}`, i))); err != nil { t.Error(err) } } - changesFirstPage, err := list.Changes().Top(1).GetChanges(&ChangeQuery{ + changesFirstPage, err := list.Changes().Top(1).GetChanges(context.Background(), &ChangeQuery{ ChangeTokenStart: token, List: true, Item: true, @@ -189,7 +190,7 @@ func TestChangesPagination(t *testing.T) { } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } } diff --git a/api/contentType.go b/api/contentType.go index 609e90e..f7f3693 100644 --- a/api/contentType.go +++ b/api/contentType.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "github.com/koltyakov/gosip" @@ -51,23 +52,23 @@ func (contentType *ContentType) ToURL() string { } // Get gets content type data object -func (contentType *ContentType) Get() (ContentTypeResp, error) { +func (contentType *ContentType) Get(ctx context.Context) (ContentTypeResp, error) { client := NewHTTPClient(contentType.client) - return client.Get(contentType.ToURL(), contentType.config) + return client.Get(ctx, contentType.ToURL(), contentType.config) } // Update updates Content Types's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.ContentType object -func (contentType *ContentType) Update(body []byte) (ContentTypeResp, error) { +func (contentType *ContentType) Update(ctx context.Context, body []byte) (ContentTypeResp, error) { body = patchMetadataType(body, "SP.ContentType") client := NewHTTPClient(contentType.client) - return client.Update(contentType.endpoint, bytes.NewBuffer(body), contentType.config) + return client.Update(ctx, contentType.endpoint, bytes.NewBuffer(body), contentType.config) } // Delete deletes a content type skipping recycle bin -func (contentType *ContentType) Delete() error { +func (contentType *ContentType) Delete(ctx context.Context) error { client := NewHTTPClient(contentType.client) - _, err := client.Delete(contentType.endpoint, contentType.config) + _, err := client.Delete(ctx, contentType.endpoint, contentType.config) return err } diff --git a/api/contentType_test.go b/api/contentType_test.go index 63653a7..419000f 100644 --- a/api/contentType_test.go +++ b/api/contentType_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "strings" "testing" @@ -21,13 +22,13 @@ func TestContentType(t *testing.T) { if err != nil { t.Error(err) } - if _, err := ct.Select("*,Fields/*").Expand("Fields").Get(); err != nil { + if _, err := ct.Select("*,Fields/*").Expand("Fields").Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Get", func(t *testing.T) { - resp, err := web.ContentTypes().Top(5).Get() + resp, err := web.ContentTypes().Top(5).Get(context.Background()) if err != nil { t.Error(err) } @@ -38,7 +39,7 @@ func TestContentType(t *testing.T) { if cts[0].Data().ID == "" { t.Error("can't get content type info") } - data, err := web.ContentTypes().GetByID(cts[0].Data().ID).Get() + data, err := web.ContentTypes().GetByID(cts[0].Data().ID).Get(context.Background()) if err != nil { t.Error(err) } @@ -55,15 +56,15 @@ func TestContentType(t *testing.T) { "Id":{"StringValue":"` + ctID + `"}, "Name":"test-temp-ct ` + guid + `" }`)) - ctResp, err := web.ContentTypes().Add(ct) + ctResp, err := web.ContentTypes().Add(context.Background(), ct) if err != nil { t.Error(err) } ctID = ctResp.Data().ID // content type ID can't be set in REST API https://github.com/pnp/pnpjs/issues/457 - if _, err := web.ContentTypes().GetByID(ctID).Update([]byte(`{"Description":"Test"}`)); err != nil { + if _, err := web.ContentTypes().GetByID(ctID).Update(context.Background(), []byte(`{"Description":"Test"}`)); err != nil { t.Error(err) } - if err := web.ContentTypes().GetByID(ctID).Delete(); err != nil { + if err := web.ContentTypes().GetByID(ctID).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -73,7 +74,7 @@ func TestContentType(t *testing.T) { func getRandomCT() (*ContentType, error) { sp := NewSP(spClient) if ctID == "" { - resp, err := sp.Web().ContentTypes().Top(1).Get() + resp, err := sp.Web().ContentTypes().Top(1).Get(context.Background()) if err != nil { return nil, err } diff --git a/api/contentTypes.go b/api/contentTypes.go index 79d33de..aee47d2 100644 --- a/api/contentTypes.go +++ b/api/contentTypes.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "regexp" "strconv" @@ -49,9 +50,9 @@ func (contentTypes *ContentTypes) ToURL() string { } // Get gets content typed queryable collection response -func (contentTypes *ContentTypes) Get() (ContentTypesResp, error) { +func (contentTypes *ContentTypes) Get(ctx context.Context) (ContentTypesResp, error) { client := NewHTTPClient(contentTypes.client) - return client.Get(contentTypes.ToURL(), contentTypes.config) + return client.Get(ctx, contentTypes.ToURL(), contentTypes.config) } // GetByID gets a content type by its ID (GUID) @@ -65,15 +66,15 @@ func (contentTypes *ContentTypes) GetByID(contentTypeID string) *ContentType { // Add adds Content Types with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.ContentType object -func (contentTypes *ContentTypes) Add(body []byte) (ContentTypeResp, error) { +func (contentTypes *ContentTypes) Add(ctx context.Context, body []byte) (ContentTypeResp, error) { // REST API doesn't work in that context as supposed to https://github.com/pnp/pnpjs/issues/457 body = patchMetadataType(body, "SP.ContentType") client := NewHTTPClient(contentTypes.client) - return client.Post(contentTypes.endpoint, bytes.NewBuffer(body), contentTypes.config) + return client.Post(ctx, contentTypes.endpoint, bytes.NewBuffer(body), contentTypes.config) } // Create adds Content Type using CSOM polyfill as REST's Add method is limited (https://github.com/pnp/pnpjs/issues/457) -func (contentTypes *ContentTypes) Create(contentTypeInfo *ContentTypeCreationInfo) (string, error) { +func (contentTypes *ContentTypes) Create(ctx context.Context, contentTypeInfo *ContentTypeCreationInfo) (string, error) { client := NewHTTPClient(contentTypes.client) b := csom.NewBuilder() @@ -126,7 +127,11 @@ func (contentTypes *ContentTypes) Create(contentTypeInfo *ContentTypeCreationInf return "", nil } - resp, err := client.ProcessQuery(contentTypes.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), contentTypes.config) + resp, err := client.ProcessQuery( + ctx, + contentTypes.client.AuthCnfg.GetSiteURL(), + bytes.NewBuffer([]byte(csomPkg)), + contentTypes.config) if err != nil { return "", nil } diff --git a/api/contentTypes_test.go b/api/contentTypes_test.go index ae4265f..369562e 100644 --- a/api/contentTypes_test.go +++ b/api/contentTypes_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "strings" "testing" @@ -20,7 +21,7 @@ func TestContentTypes(t *testing.T) { } t.Run("GetFromWeb", func(t *testing.T) { - data, err := web.ContentTypes().Select("StringId").Top(1).Get() + data, err := web.ContentTypes().Select("StringId").Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -30,20 +31,20 @@ func TestContentTypes(t *testing.T) { }) t.Run("GetFromList", func(t *testing.T) { - if _, err := web.GetList(listURI).ContentTypes().Top(1).Get(); err != nil { + if _, err := web.GetList(listURI).ContentTypes().Top(1).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("GetByID", func(t *testing.T) { - if _, err := web.ContentTypes().GetByID(contentType.ID).Get(); err != nil { + if _, err := web.ContentTypes().GetByID(contentType.ID).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("CreateUsingParentID", func(t *testing.T) { guid := uuid.New().String() - newCTID, err := web.ContentTypes().Create(&ContentTypeCreationInfo{ + newCTID, err := web.ContentTypes().Create(context.Background(), &ContentTypeCreationInfo{ Name: guid, Group: "Test", ParentContentTypeID: "0x01", @@ -54,14 +55,14 @@ func TestContentTypes(t *testing.T) { if newCTID == "" { t.Error("can't parse CT creation response") } - if err := web.ContentTypes().GetByID(newCTID).Delete(); err != nil { + if err := web.ContentTypes().GetByID(newCTID).Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("CreateUsingID", func(t *testing.T) { guid := uuid.New().String() - newCTID, err := web.ContentTypes().Create(&ContentTypeCreationInfo{ + newCTID, err := web.ContentTypes().Create(context.Background(), &ContentTypeCreationInfo{ ID: "0x0100" + strings.ToUpper(strings.Replace(guid, "-", "", -1)), Name: guid, Group: "Test", @@ -72,7 +73,7 @@ func TestContentTypes(t *testing.T) { if newCTID == "" { t.Error("can't parse CT creation response") } - if err := web.ContentTypes().GetByID(newCTID).Delete(); err != nil { + if err := web.ContentTypes().GetByID(newCTID).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -81,7 +82,7 @@ func TestContentTypes(t *testing.T) { func getAnyContentType() (*ContentTypeInfo, error) { web := NewSP(spClient).Web() - data, err := web.ContentTypes().Conf(headers.verbose).Top(1).Get() + data, err := web.ContentTypes().Conf(headers.verbose).Top(1).Get(context.Background()) if err != nil { return nil, err } diff --git a/api/context.go b/api/context.go index 60da5a9..8921faf 100644 --- a/api/context.go +++ b/api/context.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" @@ -35,9 +36,9 @@ func NewContext(client *gosip.SPClient, endpoint string, config *RequestConfig) } // Get gets context info data object -func (context *Context) Get() (*ContextInfo, error) { +func (context *Context) Get(ctx context.Context) (*ContextInfo, error) { endpoint := fmt.Sprintf("%s/_api/ContextInfo", getPriorEndpoint(context.endpoint, "/_api")) - resp, err := NewHTTPClient(context.client).Post(endpoint, nil, context.config) + resp, err := NewHTTPClient(context.client).Post(ctx, endpoint, nil, context.config) if err != nil { return nil, err } diff --git a/api/context_test.go b/api/context_test.go index 2085be9..973f915 100644 --- a/api/context_test.go +++ b/api/context_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -10,7 +11,7 @@ func TestContextInfo(t *testing.T) { sp := NewSP(spClient) t.Run("ContextInfo/SP", func(t *testing.T) { - contextInfo, err := sp.ContextInfo() + contextInfo, err := sp.ContextInfo(context.Background()) if err != nil { t.Error(err) } @@ -20,7 +21,7 @@ func TestContextInfo(t *testing.T) { }) t.Run("ContextInfo/Web", func(t *testing.T) { - contextInfo, err := sp.Web().ContextInfo() + contextInfo, err := sp.Web().ContextInfo(context.Background()) if err != nil { t.Error(err) } @@ -30,7 +31,7 @@ func TestContextInfo(t *testing.T) { }) t.Run("ContextInfo/List", func(t *testing.T) { - contextInfo, err := sp.Web().GetList("Shared Documents").ContextInfo() + contextInfo, err := sp.Web().GetList("Shared Documents").ContextInfo(context.Background()) if err != nil { t.Error(err) } diff --git a/api/csom_test.go b/api/csom_test.go index b1e77f3..6df3a52 100644 --- a/api/csom_test.go +++ b/api/csom_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" "github.com/koltyakov/gosip/csom" @@ -22,7 +23,7 @@ func TestCsomRequest(t *testing.T) { t.Error(err) } - if _, err := client.ProcessQuery(spClient.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomXML)), nil); err != nil { + if _, err := client.ProcessQuery(context.Background(), spClient.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomXML)), nil); err != nil { t.Error(err) } } diff --git a/api/customActions.go b/api/customActions.go index 6f71272..09bc409 100644 --- a/api/customActions.go +++ b/api/customActions.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -59,9 +60,9 @@ func (customActions *CustomActions) ToURL() string { } // Get gets event customActions collection -func (customActions *CustomActions) Get() ([]*CustomActionInfo, error) { +func (customActions *CustomActions) Get(ctx context.Context) ([]*CustomActionInfo, error) { client := NewHTTPClient(customActions.client) - data, err := client.Get(customActions.ToURL(), customActions.config) + data, err := client.Get(ctx, customActions.ToURL(), customActions.config) if err != nil { return nil, err } @@ -74,10 +75,10 @@ func (customActions *CustomActions) Get() ([]*CustomActionInfo, error) { } // Add register new user custom action -func (customActions *CustomActions) Add(payload []byte) (*CustomActionInfo, error) { +func (customActions *CustomActions) Add(ctx context.Context, payload []byte) (*CustomActionInfo, error) { body := patchMetadataType(payload, "SP.UserCustomAction") client := NewHTTPClient(customActions.client) - data, err := client.Post(customActions.endpoint, bytes.NewBuffer(body), customActions.config) + data, err := client.Post(ctx, customActions.endpoint, bytes.NewBuffer(body), customActions.config) if err != nil { return nil, err } @@ -118,9 +119,9 @@ func (customActions *CustomActions) GetByID(actionID string) *CustomAction { } // Get gets this action metadata -func (customAction *CustomAction) Get() (*CustomActionInfo, error) { +func (customAction *CustomAction) Get(ctx context.Context) (*CustomActionInfo, error) { client := NewHTTPClient(customAction.client) - data, err := client.Get(customAction.endpoint, customAction.config) + data, err := client.Get(ctx, customAction.endpoint, customAction.config) if err != nil { return nil, err } @@ -149,8 +150,8 @@ func (customAction *CustomAction) Get() (*CustomActionInfo, error) { // } // Delete deletes this custom action -func (customAction *CustomAction) Delete() error { +func (customAction *CustomAction) Delete(ctx context.Context) error { client := NewHTTPClient(customAction.client) - _, err := client.Delete(customAction.endpoint, customAction.config) + _, err := client.Delete(ctx, customAction.endpoint, customAction.config) return err } diff --git a/api/customActions_test.go b/api/customActions_test.go index 851d2ce..5b3aa57 100644 --- a/api/customActions_test.go +++ b/api/customActions_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "testing" ) @@ -11,7 +12,7 @@ func TestCustomActions(t *testing.T) { sp := NewSP(spClient) t.Run("Get/Site", func(t *testing.T) { - actions, err := sp.Site().CustomActions().Top(1).Get() + actions, err := sp.Site().CustomActions().Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -23,7 +24,7 @@ func TestCustomActions(t *testing.T) { }) t.Run("Get/Web", func(t *testing.T) { - actions, err := sp.Web().CustomActions().Top(1).Get() + actions, err := sp.Web().CustomActions().Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -42,12 +43,12 @@ func TestCustomActions(t *testing.T) { } // Add payload, _ := json.Marshal(info) - action, err := sp.Web().CustomActions().Add(payload) + action, err := sp.Web().CustomActions().Add(context.Background(), payload) if err != nil { t.Error(err) } // Get - action1, err := sp.Web().CustomActions().GetByID(action.ID).Get() + action1, err := sp.Web().CustomActions().GetByID(action.ID).Get(context.Background()) if err != nil { t.Error(err) } @@ -55,7 +56,7 @@ func TestCustomActions(t *testing.T) { t.Error("can't get action by ID") } // Delete - if err := sp.Web().CustomActions().GetByID(action.ID).Delete(); err != nil { + if err := sp.Web().CustomActions().GetByID(action.ID).Delete(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/eventReceivers.go b/api/eventReceivers.go index f185668..405dd4f 100644 --- a/api/eventReceivers.go +++ b/api/eventReceivers.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "github.com/koltyakov/gosip" @@ -45,9 +46,9 @@ func (eventReceivers *EventReceivers) ToURL() string { } // Get gets event receivers collection -func (eventReceivers *EventReceivers) Get() ([]*EventReceiverInfo, error) { +func (eventReceivers *EventReceivers) Get(ctx context.Context) ([]*EventReceiverInfo, error) { client := NewHTTPClient(eventReceivers.client) - data, err := client.Get(eventReceivers.ToURL(), eventReceivers.config) + data, err := client.Get(ctx, eventReceivers.ToURL(), eventReceivers.config) if err != nil { return nil, err } diff --git a/api/eventReceivers_test.go b/api/eventReceivers_test.go index 9f64097..9f0e5a2 100644 --- a/api/eventReceivers_test.go +++ b/api/eventReceivers_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -10,7 +11,7 @@ func TestEventReceivers(t *testing.T) { sp := NewSP(spClient) t.Run("Get/Site", func(t *testing.T) { - receivers, err := sp.Site().EventReceivers().Top(1).Get() + receivers, err := sp.Site().EventReceivers().Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -20,7 +21,7 @@ func TestEventReceivers(t *testing.T) { }) t.Run("Get/Web", func(t *testing.T) { - receivers, err := sp.Web().EventReceivers().Top(1).Get() + receivers, err := sp.Web().EventReceivers().Top(1).Get(context.Background()) if err != nil { t.Error(err) } diff --git a/api/features.go b/api/features.go index b43f817..126f4ca 100644 --- a/api/features.go +++ b/api/features.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -31,9 +32,9 @@ func NewFeatures(client *gosip.SPClient, endpoint string, config *RequestConfig) } // Get gets features collection (IDs) -func (features *Features) Get() ([]*FeatureInfo, error) { +func (features *Features) Get(ctx context.Context) ([]*FeatureInfo, error) { client := NewHTTPClient(features.client) - data, err := client.Get(features.endpoint, features.config) + data, err := client.Get(ctx, features.endpoint, features.config) if err != nil { return nil, err } @@ -46,19 +47,19 @@ func (features *Features) Get() ([]*FeatureInfo, error) { } // Add activates a feature by its ID (GUID) in the parent container (Site or Web) -func (features *Features) Add(featureID string, force bool) error { +func (features *Features) Add(ctx context.Context, featureID string, force bool) error { endpoint := fmt.Sprintf("%s/Add", features.endpoint) client := NewHTTPClient(features.client) body := []byte(fmt.Sprintf(`{"featdefScope":0,"featureId":"%s","force":%t}`, featureID, force)) - _, err := client.Post(endpoint, bytes.NewBuffer(body), features.config) + _, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), features.config) return err } // Remove deactivates a feature by its ID (GUID) in the parent container (Site or Web) -func (features *Features) Remove(featureID string, force bool) error { +func (features *Features) Remove(ctx context.Context, featureID string, force bool) error { endpoint := fmt.Sprintf("%s/Remove", features.endpoint) client := NewHTTPClient(features.client) body := []byte(fmt.Sprintf(`{"featureId":"%s","force":%t}`, featureID, force)) - _, err := client.Post(endpoint, bytes.NewBuffer(body), features.config) + _, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), features.config) return err } diff --git a/api/features_test.go b/api/features_test.go index 0263aef..d794862 100644 --- a/api/features_test.go +++ b/api/features_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -10,28 +11,28 @@ func TestFeatures(t *testing.T) { sp := NewSP(spClient) mdsFeatureID := "87294c72-f260-42f3-a41b-981a2ffce37a" - _ = sp.Web().Features().Remove(mdsFeatureID, true) + _ = sp.Web().Features().Remove(context.Background(), mdsFeatureID, true) t.Run("Get/Site", func(t *testing.T) { - if _, err := sp.Site().Features().Get(); err != nil { + if _, err := sp.Site().Features().Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Get/Web", func(t *testing.T) { - if _, err := sp.Web().Features().Get(); err != nil { + if _, err := sp.Web().Features().Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Add", func(t *testing.T) { - if err := sp.Web().Features().Add(mdsFeatureID, true); err != nil { + if err := sp.Web().Features().Add(context.Background(), mdsFeatureID, true); err != nil { t.Error(err) } }) t.Run("Remove", func(t *testing.T) { - if err := sp.Web().Features().Remove(mdsFeatureID, true); err != nil { + if err := sp.Web().Features().Remove(context.Background(), mdsFeatureID, true); err != nil { t.Error(err) } }) diff --git a/api/field.go b/api/field.go index ca04150..a82a19c 100644 --- a/api/field.go +++ b/api/field.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "github.com/koltyakov/gosip" ) @@ -71,9 +72,9 @@ func (field *Field) ToURL() string { } // Get gets field data object -func (field *Field) Get() (FieldResp, error) { +func (field *Field) Get(ctx context.Context) (FieldResp, error) { client := NewHTTPClient(field.client) - data, err := client.Get(field.ToURL(), field.config) + data, err := client.Get(ctx, field.ToURL(), field.config) if err != nil { return nil, err } @@ -82,15 +83,15 @@ func (field *Field) Get() (FieldResp, error) { // Update updates Field's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.Field object -func (field *Field) Update(body []byte) (FieldResp, error) { +func (field *Field) Update(ctx context.Context, body []byte) (FieldResp, error) { body = patchMetadataType(body, "SP.Field") client := NewHTTPClient(field.client) - return client.Update(field.endpoint, bytes.NewBuffer(body), field.config) + return client.Update(ctx, field.endpoint, bytes.NewBuffer(body), field.config) } // Delete deletes a field skipping recycle bin -func (field *Field) Delete() error { +func (field *Field) Delete(ctx context.Context) error { client := NewHTTPClient(field.client) - _, err := client.Delete(field.endpoint, field.config) + _, err := client.Delete(ctx, field.endpoint, field.config) return err } diff --git a/api/fieldLinks.go b/api/fieldLinks.go index 14008f1..f9a23bf 100644 --- a/api/fieldLinks.go +++ b/api/fieldLinks.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "regexp" "strconv" @@ -73,9 +74,9 @@ func (fieldLinks *FieldLinks) ToURL() string { } // Get gets fields response collection -func (fieldLinks *FieldLinks) Get() (FieldLinksResp, error) { +func (fieldLinks *FieldLinks) Get(ctx context.Context) (FieldLinksResp, error) { client := NewHTTPClient(fieldLinks.client) - return client.Get(fieldLinks.ToURL(), fieldLinks.config) + return client.Get(ctx, fieldLinks.ToURL(), fieldLinks.config) } // GetByID gets a field link by its ID (GUID) @@ -88,9 +89,9 @@ func (fieldLinks *FieldLinks) GetByID(fieldLinkID string) *FieldLink { } // Delete deletes a field link by its ID (GUID) -func (fieldLink *FieldLink) Delete() error { +func (fieldLink *FieldLink) Delete(ctx context.Context) error { client := NewHTTPClient(fieldLink.client) - _, err := client.Delete(fieldLink.endpoint, fieldLink.config) + _, err := client.Delete(ctx, fieldLink.endpoint, fieldLink.config) return err } @@ -102,7 +103,7 @@ func (fieldLink *FieldLink) Delete() error { // } // GetFields gets fields response collection -func (fieldLinks *FieldLinks) GetFields() (FieldsResp, error) { +func (fieldLinks *FieldLinks) GetFields(ctx context.Context) (FieldsResp, error) { endpoint := getPriorEndpoint(fieldLinks.endpoint, "/FieldLinks") fields := NewFields( fieldLinks.client, @@ -111,11 +112,11 @@ func (fieldLinks *FieldLinks) GetFields() (FieldsResp, error) { "contentType", ) fields.modifiers = fieldLinks.modifiers - return fields.Get() + return fields.Get(ctx) } // Add adds field link -func (fieldLinks *FieldLinks) Add(name string) (string, error) { +func (fieldLinks *FieldLinks) Add(ctx context.Context, name string) (string, error) { // // REST API doesn't work in that context as supposed to (https://social.msdn.microsoft.com/Forums/office/en-US/52dc9d24-2eb3-4540-a26a-02b12fe1155b/rest-add-fieldlink-to-content-type?forum=sharepointdevelopment) // body := []byte(TrimMultiline(fmt.Sprintf(`{ // "__metadata": { "type": "SP.FieldLink" }, @@ -140,7 +141,7 @@ func (fieldLinks *FieldLinks) Add(name string) (string, error) { getPriorEndpoint(fieldLinks.endpoint, "/FieldLinks"), fieldLinks.config, ) - resp, err := ct.Select("StringId").Get() + resp, err := ct.Select("StringId").Get(ctx) if err != nil { return "", err } @@ -172,7 +173,11 @@ func (fieldLinks *FieldLinks) Add(name string) (string, error) { } client := NewHTTPClient(fieldLinks.client) - resp, err := client.ProcessQuery(fieldLinks.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), fieldLinks.config) + resp, err := client.ProcessQuery( + ctx, + fieldLinks.client.AuthCnfg.GetSiteURL(), + bytes.NewBuffer([]byte(csomPkg)), + fieldLinks.config) if err != nil { return "", err } diff --git a/api/fieldLinks_test.go b/api/fieldLinks_test.go index 459c216..0dc4c88 100644 --- a/api/fieldLinks_test.go +++ b/api/fieldLinks_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "strings" "testing" @@ -19,14 +20,14 @@ func TestFieldLinks(t *testing.T) { "Id": {"StringValue":"` + ctID + `"}, "Name":"test-temp-ct ` + guid + `" }`)) - ctResp, err := web.ContentTypes().Add(ct) + ctResp, err := web.ContentTypes().Add(context.Background(), ct) if err != nil { t.Error(err) } ctID = ctResp.Data().ID // content type ID can't be set in REST API https://github.com/pnp/pnpjs/issues/457 t.Run("Get", func(t *testing.T) { - resp, err := web.ContentTypes().GetByID(ctID).FieldLinks().Get() + resp, err := web.ContentTypes().GetByID(ctID).FieldLinks().Get(context.Background()) if err != nil { t.Error(err) } @@ -42,7 +43,7 @@ func TestFieldLinks(t *testing.T) { }) t.Run("GetFields", func(t *testing.T) { - resp, err := web.ContentTypes().GetByID(ctID).FieldLinks().GetFields() + resp, err := web.ContentTypes().GetByID(ctID).FieldLinks().GetFields(context.Background()) if err != nil { t.Error(err) } @@ -58,23 +59,23 @@ func TestFieldLinks(t *testing.T) { }) t.Run("Add", func(t *testing.T) { - fl, err := web.ContentTypes().GetByID(ctID).FieldLinks().Add("Language") + fl, err := web.ContentTypes().GetByID(ctID).FieldLinks().Add(context.Background(), "Language") if err != nil { t.Error(err) } if fl == "" { t.Error("can't parse field link add response") } - fls, _ := web.ContentTypes().GetByID(ctID).FieldLinks().Get() + fls, _ := web.ContentTypes().GetByID(ctID).FieldLinks().Get(context.Background()) if len(fls.Data()) < 3 { t.Error("failed adding field link") } - if err := web.ContentTypes().GetByID(ctID).FieldLinks().GetByID(fl).Delete(); err != nil { + if err := web.ContentTypes().GetByID(ctID).FieldLinks().GetByID(fl).Delete(context.Background()); err != nil { t.Error(err) } }) - if err := web.ContentTypes().GetByID(ctID).Delete(); err != nil { + if err := web.ContentTypes().GetByID(ctID).Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/field_test.go b/api/field_test.go index e7f2fc9..12dfde5 100644 --- a/api/field_test.go +++ b/api/field_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "testing" @@ -20,7 +21,7 @@ func TestField(t *testing.T) { } t.Run("Get", func(t *testing.T) { - data, err := field.Select("Id").Get() + data, err := field.Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -35,14 +36,14 @@ func TestField(t *testing.T) { t.Run("UpdateDelete", func(t *testing.T) { guid := uuid.New().String() fm := []byte(`{"__metadata":{"type":"SP.FieldText"},"Title":"test-temp-` + guid + `","FieldTypeKind":2,"MaxLength":255}`) - d, err := web.Fields().Add(fm) + d, err := web.Fields().Add(context.Background(), fm) if err != nil { t.Error(err) } - if _, err := web.Fields().GetByID(d.Data().ID).Update([]byte(`{"Description":"Test"}`)); err != nil { + if _, err := web.Fields().GetByID(d.Data().ID).Update(context.Background(), []byte(`{"Description":"Test"}`)); err != nil { t.Error(err) } - if err := web.Fields().GetByID(d.Data().ID).Delete(); err != nil { + if err := web.Fields().GetByID(d.Data().ID).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -52,7 +53,7 @@ func TestField(t *testing.T) { func getRandomField() (*Field, error) { sp := NewSP(spClient) if fieldID == "" { - resp, err := sp.Web().Fields().Top(1).Get() + resp, err := sp.Web().Fields().Top(1).Get(context.Background()) if err != nil { return nil, err } diff --git a/api/fields.go b/api/fields.go index f7e6607..f58df09 100644 --- a/api/fields.go +++ b/api/fields.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -40,23 +41,23 @@ func (fields *Fields) ToURL() string { } // Get gets fields response collection -func (fields *Fields) Get() (FieldsResp, error) { +func (fields *Fields) Get(ctx context.Context) (FieldsResp, error) { client := NewHTTPClient(fields.client) - return client.Get(fields.ToURL(), fields.config) + return client.Get(ctx, fields.ToURL(), fields.config) } // Add adds field with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.Field object -func (fields *Fields) Add(body []byte) (FieldResp, error) { +func (fields *Fields) Add(ctx context.Context, body []byte) (FieldResp, error) { body = patchMetadataType(body, "SP.Field") client := NewHTTPClient(fields.client) - return client.Post(fields.endpoint, bytes.NewBuffer(body), fields.config) + return client.Post(ctx, fields.endpoint, bytes.NewBuffer(body), fields.config) } // CreateFieldAsXML creates a field using XML schema definition // `options` parameter (https://github.com/pnp/pnpjs/blob/version-2/packages/sp/fields/types.ts#L553) // is only relevant for adding fields in list instances -func (fields *Fields) CreateFieldAsXML(schemaXML string, options int) (FieldResp, error) { +func (fields *Fields) CreateFieldAsXML(ctx context.Context, schemaXML string, options int) (FieldResp, error) { endpoint := fmt.Sprintf("%s/CreateFieldAsXml", fields.endpoint) info := map[string]map[string]interface{}{ "parameters": { @@ -74,7 +75,7 @@ func (fields *Fields) CreateFieldAsXML(schemaXML string, options int) (FieldResp return nil, err } client := NewHTTPClient(fields.client) - return client.Post(endpoint, bytes.NewBuffer(payload), fields.config) + return client.Post(ctx, endpoint, bytes.NewBuffer(payload), fields.config) } // GetByID gets a field by its ID (GUID) diff --git a/api/fields_test.go b/api/fields_test.go index 04d9747..a2e05da 100644 --- a/api/fields_test.go +++ b/api/fields_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "strings" "testing" @@ -20,7 +21,7 @@ func TestFields(t *testing.T) { } t.Run("GetFromWeb", func(t *testing.T) { - data, err := web.Fields().Top(1).Get() + data, err := web.Fields().Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -30,7 +31,7 @@ func TestFields(t *testing.T) { }) t.Run("GetFromList", func(t *testing.T) { - if _, err := web.GetList(listURI).Fields().Top(1).Get(); err != nil { + if _, err := web.GetList(listURI).Fields().Top(1).Get(context.Background()); err != nil { t.Error(err) } }) @@ -46,22 +47,22 @@ func TestFields(t *testing.T) { // }) t.Run("GetByID", func(t *testing.T) { - if _, err := web.Fields().GetByID(field.ID).Get(); err != nil { + if _, err := web.Fields().GetByID(field.ID).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("GetByTitle", func(t *testing.T) { - if _, err := web.Fields().GetByTitle(field.Title).Get(); err != nil { + if _, err := web.Fields().GetByTitle(field.Title).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("GetByInternalNameOrTitle", func(t *testing.T) { - if _, err := web.Fields().GetByInternalNameOrTitle(field.InternalName).Get(); err != nil { + if _, err := web.Fields().GetByInternalNameOrTitle(field.InternalName).Get(context.Background()); err != nil { t.Error(err) } - if _, err := web.Fields().GetByInternalNameOrTitle(field.Title).Get(); err != nil { + if _, err := web.Fields().GetByInternalNameOrTitle(field.Title).Get(context.Background()); err != nil { t.Error(err) } }) @@ -69,10 +70,10 @@ func TestFields(t *testing.T) { t.Run("Add", func(t *testing.T) { title := strings.Replace(uuid.New().String(), "-", "", -1) fm := []byte(`{"__metadata":{"type":"SP.FieldText"},"Title":"` + title + `","FieldTypeKind":2,"MaxLength":255}`) - if _, err := web.Fields().Add(fm); err != nil { + if _, err := web.Fields().Add(context.Background(), fm); err != nil { t.Error(err) } - if err := web.Fields().GetByInternalNameOrTitle(title).Delete(); err != nil { + if err := web.Fields().GetByInternalNameOrTitle(title).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -84,7 +85,7 @@ func TestFields(t *testing.T) { func getAnyField() (*FieldInfo, error) { web := NewSP(spClient).Web() - data, err := web.Fields().Top(1).Get() + data, err := web.Fields().Top(1).Get(context.Background()) if err != nil { return nil, err } diff --git a/api/file.go b/api/file.go index e6b5d4e..3e335d0 100644 --- a/api/file.go +++ b/api/file.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "io" @@ -81,28 +82,28 @@ func (file *File) ToURL() string { } // Get gets file data object -func (file *File) Get() (FileResp, error) { +func (file *File) Get(ctx context.Context) (FileResp, error) { client := NewHTTPClient(file.client) - return client.Get(file.ToURL(), file.config) + return client.Get(ctx, file.ToURL(), file.config) } // Delete deletes this file skipping recycle bin -func (file *File) Delete() error { +func (file *File) Delete(ctx context.Context) error { client := NewHTTPClient(file.client) - _, err := client.Delete(file.endpoint, file.config) + _, err := client.Delete(ctx, file.endpoint, file.config) return err } // Recycle moves this file to the recycle bin -func (file *File) Recycle() error { +func (file *File) Recycle(ctx context.Context) error { client := NewHTTPClient(file.client) endpoint := fmt.Sprintf("%s/Recycle", file.endpoint) - _, err := client.Post(endpoint, nil, file.config) + _, err := client.Post(ctx, endpoint, nil, file.config) return err } // ListItemAllFields gets this file Item data object metadata -func (file *File) ListItemAllFields() (ListItemAllFieldsResp, error) { +func (file *File) ListItemAllFields(ctx context.Context) (ListItemAllFieldsResp, error) { endpoint := fmt.Sprintf("%s/ListItemAllFields", file.endpoint) apiURL, _ := url.Parse(endpoint) @@ -114,7 +115,7 @@ func (file *File) ListItemAllFields() (ListItemAllFieldsResp, error) { apiURL.RawQuery = query.Encode() client := NewHTTPClient(file.client) - data, err := client.Get(apiURL.String(), file.config) + data, err := client.Get(ctx, apiURL.String(), file.config) if err != nil { return nil, err } @@ -123,9 +124,9 @@ func (file *File) ListItemAllFields() (ListItemAllFieldsResp, error) { } // GetItem gets this folder Item API object metadata -func (file *File) GetItem() (*Item, error) { +func (file *File) GetItem(ctx context.Context) (*Item, error) { scoped := NewFile(file.client, file.endpoint, file.config) - data, err := scoped.Conf(HeadersPresets.Verbose).Select("Id").ListItemAllFields() + data, err := scoped.Conf(HeadersPresets.Verbose).Select("Id").ListItemAllFields(ctx) if err != nil { return nil, err } @@ -150,7 +151,7 @@ func (file *File) GetItem() (*Item, error) { } // CheckIn checks file in, checkInType: 0 - Minor, 1 - Major, 2 - Overwrite -func (file *File) CheckIn(comment string, checkInType int) ([]byte, error) { +func (file *File) CheckIn(ctx context.Context, comment string, checkInType int) ([]byte, error) { endpoint := fmt.Sprintf( "%s/CheckIn(comment='%s',checkintype=%d)", file.endpoint, @@ -158,50 +159,50 @@ func (file *File) CheckIn(comment string, checkInType int) ([]byte, error) { checkInType, ) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // CheckOut checks file out -func (file *File) CheckOut() ([]byte, error) { +func (file *File) CheckOut(ctx context.Context) ([]byte, error) { endpoint := fmt.Sprintf("%s/CheckOut", file.endpoint) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // UndoCheckOut undoes file check out -func (file *File) UndoCheckOut() ([]byte, error) { +func (file *File) UndoCheckOut(ctx context.Context) ([]byte, error) { endpoint := fmt.Sprintf("%s/UndoCheckOut", file.endpoint) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // Publish publishes a file -func (file *File) Publish(comment string) ([]byte, error) { +func (file *File) Publish(ctx context.Context, comment string) ([]byte, error) { endpoint := fmt.Sprintf( "%s/Publish(comment='%s')", file.endpoint, comment, ) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // UnPublish un-publishes a file -func (file *File) UnPublish(comment string) ([]byte, error) { +func (file *File) UnPublish(ctx context.Context, comment string) ([]byte, error) { endpoint := fmt.Sprintf( "%s/Publish(comment='%s')", file.endpoint, comment, ) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // GetReader gets file io.ReadCloser -func (file *File) GetReader() (io.ReadCloser, error) { +func (file *File) GetReader(ctx context.Context) (io.ReadCloser, error) { endpoint := fmt.Sprintf("%s/$value", file.endpoint) - req, err := http.NewRequest("GET", endpoint, nil) + req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil) if err != nil { return nil, err } @@ -224,8 +225,8 @@ func (file *File) GetReader() (io.ReadCloser, error) { } // Download file bytes -func (file *File) Download() ([]byte, error) { - body, err := file.GetReader() +func (file *File) Download(ctx context.Context) ([]byte, error) { + body, err := file.GetReader(ctx) if err != nil { return nil, err } @@ -239,26 +240,26 @@ func (file *File) Download() ([]byte, error) { } // MoveTo file to new location within the same site -func (file *File) MoveTo(newURL string, overwrite bool) ([]byte, error) { +func (file *File) MoveTo(ctx context.Context, newURL string, overwrite bool) ([]byte, error) { flag := 0 if overwrite { flag = 1 } endpoint := fmt.Sprintf("%s/MoveTo(newurl='%s',flags=%d)", file.endpoint, newURL, flag) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // CopyTo file to new location within the same site -func (file *File) CopyTo(newURL string, overwrite bool) ([]byte, error) { +func (file *File) CopyTo(ctx context.Context, newURL string, overwrite bool) ([]byte, error) { endpoint := fmt.Sprintf("%s/CopyTo(strnewurl='%s',boverwrite=%t)", file.endpoint, newURL, overwrite) client := NewHTTPClient(file.client) - return client.Post(endpoint, nil, file.config) + return client.Post(ctx, endpoint, nil, file.config) } // ContextInfo ... -func (file *File) ContextInfo() (*ContextInfo, error) { - return NewContext(file.client, file.ToURL(), file.config).Get() +func (file *File) ContextInfo(ctx context.Context) (*ContextInfo, error) { + return NewContext(file.client, file.ToURL(), file.config).Get(ctx) } // Props gets Properties API instance queryable collection for this File diff --git a/api/file_test.go b/api/file_test.go index 5402931..29389c8 100644 --- a/api/file_test.go +++ b/api/file_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "io" "testing" @@ -16,13 +17,13 @@ func TestFile(t *testing.T) { newFolderName := uuid.New().String() rootFolderURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" newFolderURI := rootFolderURI + "/" + newFolderName - if _, err := web.GetFolder(rootFolderURI).Folders().Add(newFolderName); err != nil { + if _, err := web.GetFolder(rootFolderURI).Folders().Add(context.Background(), newFolderName); err != nil { t.Error(err) } // Create a temporary document library with minor versioning enabled tempDocLibName := uuid.New().String() - if _, err := web.Lists().Add(tempDocLibName, map[string]interface{}{ + if _, err := web.Lists().Add(context.Background(), tempDocLibName, map[string]interface{}{ "BaseTemplate": 101, "EnableMinorVersions": true, }); err != nil { @@ -33,29 +34,29 @@ func TestFile(t *testing.T) { for i := 1; i <= 5; i++ { fileName := fmt.Sprintf("File_%d.txt", i) fileData := []byte(fmt.Sprintf("File %d data", i)) - if _, err := web.GetFolder(newFolderURI).Files().Add(fileName, fileData, true); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().Add(context.Background(), fileName, fileData, true); err != nil { t.Error(err) } } }) t.Run("CheckOut", func(t *testing.T) { - if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").CheckOut(); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").CheckOut(context.Background()); err != nil { t.Error(err) } }) t.Run("UndoCheckOut", func(t *testing.T) { - if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").UndoCheckOut(); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").UndoCheckOut(context.Background()); err != nil { t.Error(err) } }) t.Run("CheckIn", func(t *testing.T) { - if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").CheckOut(); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").CheckOut(context.Background()); err != nil { t.Error(err) } - if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").CheckIn("test", CheckInTypes.Major); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").CheckIn(context.Background(), "test", CheckInTypes.Major); err != nil { t.Error(err) } }) @@ -63,13 +64,13 @@ func TestFile(t *testing.T) { t.Run("PubUnPub", func(t *testing.T) { // Using temporary document library with minor versioning enabled lib := web.Lists().GetByTitle(tempDocLibName) - if _, err := lib.RootFolder().Files().Add("File_1.txt", []byte("File 1 data"), true); err != nil { + if _, err := lib.RootFolder().Files().Add(context.Background(), "File_1.txt", []byte("File 1 data"), true); err != nil { t.Error(err) } - if _, err := lib.RootFolder().Files().GetByName("File_1.txt").Publish("test"); err != nil { + if _, err := lib.RootFolder().Files().GetByName("File_1.txt").Publish(context.Background(), "test"); err != nil { t.Error(err) } - if _, err := lib.RootFolder().Files().GetByName("File_1.txt").UnPublish("test"); err != nil { + if _, err := lib.RootFolder().Files().GetByName("File_1.txt").UnPublish(context.Background(), "test"); err != nil { t.Error(err) } }) @@ -80,32 +81,32 @@ func TestFile(t *testing.T) { } file := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt") - props, err := file.Props().Get() + props, err := file.Props().Get(context.Background()) if err != nil { t.Error(err) } if len(props.Data()) == 0 { t.Error("can't get file properties") } - if err := file.Props().Set("MyProp", "MyValue"); err != nil { + if err := file.Props().Set(context.Background(), "MyProp", "MyValue"); err != nil { t.Error("can't set file property") } }) t.Run("Delete", func(t *testing.T) { - if err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").Delete(); err != nil { + if err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("Recycle", func(t *testing.T) { - if err := web.GetFile(newFolderURI + "/File_2.txt").Recycle(); err != nil { + if err := web.GetFile(newFolderURI + "/File_2.txt").Recycle(context.Background()); err != nil { t.Error(err) } }) t.Run("Get", func(t *testing.T) { - data, err := web.GetFile(newFolderURI + "/File_3.txt").Get() + data, err := web.GetFile(newFolderURI + "/File_3.txt").Get(context.Background()) if err != nil { t.Error(err) } @@ -115,11 +116,11 @@ func TestFile(t *testing.T) { }) t.Run("GetFileByID", func(t *testing.T) { - data, err := web.GetFile(newFolderURI + "/File_3.txt").Get() + data, err := web.GetFile(newFolderURI + "/File_3.txt").Get(context.Background()) if err != nil { t.Error(err) } - d, err := web.GetFileByID(data.Data().UniqueID).Get() + d, err := web.GetFileByID(data.Data().UniqueID).Get(context.Background()) if err != nil { t.Error(err) } @@ -130,11 +131,11 @@ func TestFile(t *testing.T) { }) t.Run("GetFileByPath", func(t *testing.T) { - data, err := web.GetFile(newFolderURI + "/File_3.txt").Get() + data, err := web.GetFile(newFolderURI + "/File_3.txt").Get(context.Background()) if err != nil { t.Error(err) } - d, err := web.GetFileByPath(data.Data().ServerRelativeURL).Get() + d, err := web.GetFileByPath(data.Data().ServerRelativeURL).Get(context.Background()) if err != nil { t.Error(err) } @@ -145,11 +146,11 @@ func TestFile(t *testing.T) { }) t.Run("GetItem", func(t *testing.T) { - item, err := web.GetFile(newFolderURI + "/File_3.txt").GetItem() + item, err := web.GetFile(newFolderURI + "/File_3.txt").GetItem(context.Background()) if err != nil { t.Error(err) } - data, err := item.Select("Id").Get() + data, err := item.Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -160,10 +161,10 @@ func TestFile(t *testing.T) { t.Run("GetReader", func(t *testing.T) { fileContent := []byte("file content") - if _, err := web.GetFolder(newFolderURI).Files().Add("reader.txt", fileContent, true); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().Add(context.Background(), "reader.txt", fileContent, true); err != nil { t.Error(err) } - reader, err := web.GetFile(newFolderURI + "/reader.txt").GetReader() + reader, err := web.GetFile(newFolderURI + "/reader.txt").GetReader(context.Background()) if err != nil { t.Error(err) } @@ -178,17 +179,17 @@ func TestFile(t *testing.T) { }) t.Run("ContextInfo", func(t *testing.T) { - if _, err := web.GetFile(newFolderURI + "/File_3.txt").ContextInfo(); err != nil { + if _, err := web.GetFile(newFolderURI + "/File_3.txt").ContextInfo(context.Background()); err != nil { t.Error(err) } }) t.Run("Download", func(t *testing.T) { fileContent := []byte("file content") - if _, err := web.GetFolder(newFolderURI).Files().Add("download.txt", fileContent, true); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().Add(context.Background(), "download.txt", fileContent, true); err != nil { t.Error(err) } - content, err := web.GetFile(newFolderURI + "/download.txt").Download() + content, err := web.GetFile(newFolderURI + "/download.txt").Download(context.Background()) if err != nil { t.Error(err) } @@ -198,22 +199,22 @@ func TestFile(t *testing.T) { }) t.Run("MoveTo", func(t *testing.T) { - if _, err := web.GetFile(newFolderURI+"/File_4.txt").MoveTo(newFolderURI+"/File_4_moved.txt", true); err != nil { + if _, err := web.GetFile(newFolderURI+"/File_4.txt").MoveTo(context.Background(), newFolderURI+"/File_4_moved.txt", true); err != nil { t.Error(err) } }) t.Run("CopyTo", func(t *testing.T) { - if _, err := web.GetFile(newFolderURI+"/File_5.txt").CopyTo(newFolderURI+"/File_5_copyed.txt", true); err != nil { + if _, err := web.GetFile(newFolderURI+"/File_5.txt").CopyTo(context.Background(), newFolderURI+"/File_5_copyed.txt", true); err != nil { t.Error(err) } }) // Clean up - if err := web.GetFolder(newFolderURI).Delete(); err != nil { + if err := web.GetFolder(newFolderURI).Delete(context.Background()); err != nil { t.Error(err) } - if err := web.Lists().GetByTitle(tempDocLibName).Delete(); err != nil { + if err := web.Lists().GetByTitle(tempDocLibName).Delete(context.Background()); err != nil { t.Error(err) } } diff --git a/api/files.go b/api/files.go index cc81ee6..964e593 100644 --- a/api/files.go +++ b/api/files.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "github.com/koltyakov/gosip" @@ -37,9 +38,9 @@ func (files *Files) ToURL() string { } // Get gets Files collection response -func (files *Files) Get() (FilesResp, error) { +func (files *Files) Get(ctx context.Context) (FilesResp, error) { client := NewHTTPClient(files.client) - return client.Get(files.ToURL(), files.config) + return client.Get(ctx, files.ToURL(), files.config) } // GetByName gets a file by its name @@ -52,8 +53,8 @@ func (files *Files) GetByName(fileName string) *File { } // Add uploads file into the folder -func (files *Files) Add(name string, content []byte, overwrite bool) (FileResp, error) { +func (files *Files) Add(ctx context.Context, name string, content []byte, overwrite bool) (FileResp, error) { client := NewHTTPClient(files.client) endpoint := fmt.Sprintf("%s/Add(overwrite=%t,url='%s')", files.endpoint, overwrite, name) - return client.Post(endpoint, bytes.NewBuffer(content), files.config) + return client.Post(ctx, endpoint, bytes.NewBuffer(content), files.config) } diff --git a/api/filesChunked.go b/api/filesChunked.go index 91aae4c..f2bdae5 100644 --- a/api/filesChunked.go +++ b/api/filesChunked.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "io" @@ -27,13 +28,13 @@ type FileUploadProgressData struct { } // AddChunked uploads a file in chunks (streaming), is a good fit for large files. Supported starting from SharePoint 2016. -func (files *Files) AddChunked(name string, stream io.Reader, options *AddChunkedOptions) (FileResp, error) { +func (files *Files) AddChunked(ctx context.Context, name string, stream io.Reader, options *AddChunkedOptions) (FileResp, error) { web := NewSP(files.client).Web().Conf(files.config) var file *File uploadID := uuid.New().String() - cancelUpload := func(file *File, uploadID string) error { - if err := file.cancelUpload(uploadID); err != nil { + cancelUpload := func(ctx context.Context, file *File, uploadID string) error { + if err := file.cancelUpload(ctx, uploadID); err != nil { return err } return fmt.Errorf("file upload was canceled") @@ -73,19 +74,19 @@ func (files *Files) AddChunked(name string, stream io.Reader, options *AddChunke // Upload in a call if file size is less than chunk size if size < options.ChunkSize && progress.BlockNumber == 0 { - return files.Add(name, chunk, options.Overwrite) + return files.Add(ctx, name, chunk, options.Overwrite) } // Finishing uploading chunked file if size < options.ChunkSize && progress.BlockNumber > 0 { progress.Stage = "finishing" if !options.Progress(progress) { - return nil, cancelUpload(file, uploadID) + return nil, cancelUpload(ctx, file, uploadID) } if file == nil { return nil, fmt.Errorf("can't get file object") } - return file.finishUpload(uploadID, progress.FileOffset, chunk) + return file.finishUpload(ctx, uploadID, progress.FileOffset, chunk) } // Initial chunked upload @@ -94,12 +95,12 @@ func (files *Files) AddChunked(name string, stream io.Reader, options *AddChunke if !options.Progress(progress) { return nil, fmt.Errorf("file upload was canceled") // cancelUpload(file, uploadID) } - fileResp, err := files.Add(name, nil, options.Overwrite) + fileResp, err := files.Add(ctx, name, nil, options.Overwrite) if err != nil { return nil, err } file = web.GetFile(fileResp.Data().ServerRelativeURL) - offset, err := file.startUpload(uploadID, chunk) + offset, err := file.startUpload(ctx, uploadID, chunk) if err != nil { return nil, err } @@ -107,12 +108,12 @@ func (files *Files) AddChunked(name string, stream io.Reader, options *AddChunke } else { // or continue chunk upload progress.Stage = "continue" if !options.Progress(progress) { - return nil, cancelUpload(file, uploadID) + return nil, cancelUpload(ctx, file, uploadID) } if file == nil { return nil, fmt.Errorf("can't get file object") } - offset, err := file.continueUpload(uploadID, progress.FileOffset, chunk) + offset, err := file.continueUpload(ctx, uploadID, progress.FileOffset, chunk) if err != nil { return nil, err } @@ -124,19 +125,19 @@ func (files *Files) AddChunked(name string, stream io.Reader, options *AddChunke progress.Stage = "finishing" if !options.Progress(progress) { - return nil, cancelUpload(file, uploadID) + return nil, cancelUpload(ctx, file, uploadID) } if file == nil { return nil, fmt.Errorf("can't get file object") } - return file.finishUpload(uploadID, progress.FileOffset, nil) + return file.finishUpload(ctx, uploadID, progress.FileOffset, nil) } // startUpload starts uploading a document using chunk API -func (file *File) startUpload(uploadID string, chunk []byte) (int, error) { +func (file *File) startUpload(ctx context.Context, uploadID string, chunk []byte) (int, error) { client := NewHTTPClient(file.client) endpoint := fmt.Sprintf("%s/StartUpload(uploadId=guid'%s')", file.endpoint, uploadID) - data, err := client.Post(endpoint, bytes.NewBuffer(chunk), file.config) + data, err := client.Post(ctx, endpoint, bytes.NewBuffer(chunk), file.config) if err != nil { return 0, err } @@ -159,10 +160,10 @@ func (file *File) startUpload(uploadID string, chunk []byte) (int, error) { } // continueUpload continues uploading a document using chunk API -func (file *File) continueUpload(uploadID string, fileOffset int, chunk []byte) (int, error) { +func (file *File) continueUpload(ctx context.Context, uploadID string, fileOffset int, chunk []byte) (int, error) { client := NewHTTPClient(file.client) endpoint := fmt.Sprintf("%s/ContinueUpload(uploadId=guid'%s',fileOffset=%d)", file.endpoint, uploadID, fileOffset) - data, err := client.Post(endpoint, bytes.NewBuffer(chunk), file.config) + data, err := client.Post(ctx, endpoint, bytes.NewBuffer(chunk), file.config) if err != nil { return 0, err } @@ -185,16 +186,16 @@ func (file *File) continueUpload(uploadID string, fileOffset int, chunk []byte) } // cancelUpload cancels document upload using chunk API -func (file *File) cancelUpload(uploadID string) error { +func (file *File) cancelUpload(ctx context.Context, uploadID string) error { client := NewHTTPClient(file.client) endpoint := fmt.Sprintf("%s/CancelUpload(uploadId=guid'%s')", file.endpoint, uploadID) - _, err := client.Post(endpoint, nil, file.config) + _, err := client.Post(ctx, endpoint, nil, file.config) return err } // finishUpload finishes uploading a document using chunk API -func (file *File) finishUpload(uploadID string, fileOffset int, chunk []byte) (FileResp, error) { +func (file *File) finishUpload(ctx context.Context, uploadID string, fileOffset int, chunk []byte) (FileResp, error) { client := NewHTTPClient(file.client) endpoint := fmt.Sprintf("%s/FinishUpload(uploadId=guid'%s',fileOffset=%d)", file.endpoint, uploadID, fileOffset) - return client.Post(endpoint, bytes.NewBuffer(chunk), file.config) + return client.Post(ctx, endpoint, bytes.NewBuffer(chunk), file.config) } diff --git a/api/filesChunked_test.go b/api/filesChunked_test.go index c01a6c0..d589043 100644 --- a/api/filesChunked_test.go +++ b/api/filesChunked_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "strings" "testing" @@ -19,14 +20,14 @@ func TestFilesChunked(t *testing.T) { newFolderName := uuid.New().String() rootFolderURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" newFolderURI := rootFolderURI + "/" + newFolderName - if _, err := web.GetFolder(rootFolderURI).Folders().Add(newFolderName); err != nil { + if _, err := web.GetFolder(rootFolderURI).Folders().Add(context.Background(), newFolderName); err != nil { t.Error(err) } t.Run("AddChunkedMicro", func(t *testing.T) { fileName := "TinyFile.txt" stream := strings.NewReader("Less than a chunk content") - if _, err := web.GetFolder(newFolderURI).Files().AddChunked(fileName, stream, nil); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().AddChunked(context.Background(), fileName, stream, nil); err != nil { t.Error(err) } }) @@ -39,11 +40,11 @@ func TestFilesChunked(t *testing.T) { Overwrite: true, ChunkSize: 5, } - fileResp, err := web.GetFolder(newFolderURI).Files().AddChunked(fileName, stream, options) + fileResp, err := web.GetFolder(newFolderURI).Files().AddChunked(context.Background(), fileName, stream, options) if err != nil { t.Error(err) } - data, err := web.GetFile(fileResp.Data().ServerRelativeURL).Download() + data, err := web.GetFile(fileResp.Data().ServerRelativeURL).Download(context.Background()) if err != nil { t.Error(err) } @@ -71,7 +72,7 @@ func TestFilesChunked(t *testing.T) { } _, _ = web.GetFolder(newFolderURI).Files(). Conf(reqConfig). - AddChunked(fileName, stream, options) + AddChunked(context.Background(), fileName, stream, options) if offset == 0 { t.Error("wrong offset value") @@ -87,7 +88,7 @@ func TestFilesChunked(t *testing.T) { Overwrite: true, ChunkSize: 5, } - if _, err := web.GetFolder(newFolderURI).Files().AddChunked(fileName, stream, options); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().AddChunked(context.Background(), fileName, stream, options); err != nil { t.Error(err) } }) @@ -100,7 +101,7 @@ func TestFilesChunked(t *testing.T) { Overwrite: true, ChunkSize: 0, } - if _, err := web.GetFolder(newFolderURI).Files().AddChunked(fileName, stream, options); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().AddChunked(context.Background(), fileName, stream, options); err != nil { t.Error(err) } }) @@ -116,7 +117,7 @@ func TestFilesChunked(t *testing.T) { return data.BlockNumber <= 0 // cancel upload after first chunk }, } - _, err := web.GetFolder(newFolderURI).Files().AddChunked(fileName, stream, options) + _, err := web.GetFolder(newFolderURI).Files().AddChunked(context.Background(), fileName, stream, options) if err == nil { t.Error("cancel upload was not handled") } @@ -136,7 +137,7 @@ func TestFilesChunked(t *testing.T) { return false // cancel upload immediately }, } - _, err := web.GetFolder(newFolderURI).Files().AddChunked(fileName, stream, options) + _, err := web.GetFolder(newFolderURI).Files().AddChunked(context.Background(), fileName, stream, options) if err == nil { t.Error("cancel upload was not handled") } @@ -145,7 +146,7 @@ func TestFilesChunked(t *testing.T) { } }) - if err := web.GetFolder(newFolderURI).Delete(); err != nil { + if err := web.GetFolder(newFolderURI).Delete(context.Background()); err != nil { t.Error(err) } } diff --git a/api/files_test.go b/api/files_test.go index d3e9f2a..44178e7 100644 --- a/api/files_test.go +++ b/api/files_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "testing" @@ -15,7 +16,7 @@ func TestFiles(t *testing.T) { newFolderName := uuid.New().String() rootFolderURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" newFolderURI := rootFolderURI + "/" + newFolderName - if _, err := web.GetFolder(rootFolderURI).Folders().Add(newFolderName); err != nil { + if _, err := web.GetFolder(rootFolderURI).Folders().Add(context.Background(), newFolderName); err != nil { t.Error(err) } @@ -23,14 +24,14 @@ func TestFiles(t *testing.T) { for i := 1; i <= 5; i++ { fileName := fmt.Sprintf("File_%d.txt", i) fileData := []byte(fmt.Sprintf("File %d data", i)) - if _, err := web.GetFolder(newFolderURI).Files().Add(fileName, fileData, true); err != nil { + if _, err := web.GetFolder(newFolderURI).Files().Add(context.Background(), fileName, fileData, true); err != nil { t.Error(err) } } }) t.Run("Get", func(t *testing.T) { - data, err := web.GetFolder(newFolderURI).Files().Get() + data, err := web.GetFolder(newFolderURI).Files().Get(context.Background()) if err != nil { t.Error(err) } @@ -43,7 +44,7 @@ func TestFiles(t *testing.T) { }) t.Run("GetByName", func(t *testing.T) { - data, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").Get() + data, err := web.GetFolder(newFolderURI).Files().GetByName("File_1.txt").Get(context.Background()) if err != nil { t.Error(err) } @@ -53,7 +54,7 @@ func TestFiles(t *testing.T) { }) t.Run("GetFile", func(t *testing.T) { - data, err := web.GetFile(newFolderURI + "/File_2.txt").Get() + data, err := web.GetFile(newFolderURI + "/File_2.txt").Get(context.Background()) if err != nil { t.Error(err) } @@ -67,7 +68,7 @@ func TestFiles(t *testing.T) { t.Skip("is not supported with legacy SP") } - data, err := web.GetFileByPath(newFolderURI + "/File_2.txt").Get() + data, err := web.GetFileByPath(newFolderURI + "/File_2.txt").Get(context.Background()) if err != nil { t.Error(err) } @@ -81,16 +82,16 @@ func TestFiles(t *testing.T) { t.Skip("is not supported with legacy SP") } - data, err := web.GetFile(newFolderURI + "/File_2.txt").Select("UniqueId").Get() + data, err := web.GetFile(newFolderURI + "/File_2.txt").Select("UniqueId").Get(context.Background()) if err != nil { t.Error(err) } - if _, err := web.GetFileByID(data.Data().UniqueID).Get(); err != nil { + if _, err := web.GetFileByID(data.Data().UniqueID).Get(context.Background()); err != nil { t.Error(err) } }) - if err := web.GetFolder(newFolderURI).Delete(); err != nil { + if err := web.GetFolder(newFolderURI).Delete(context.Background()); err != nil { t.Error(err) } } diff --git a/api/folder.go b/api/folder.go index 88e9ec3..2191779 100644 --- a/api/folder.go +++ b/api/folder.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "net/url" @@ -55,31 +56,31 @@ func (folder *Folder) ToURL() string { } // Get gets this folder data object -func (folder *Folder) Get() (FolderResp, error) { +func (folder *Folder) Get(ctx context.Context) (FolderResp, error) { client := NewHTTPClient(folder.client) - return client.Get(folder.ToURL(), folder.config) + return client.Get(ctx, folder.ToURL(), folder.config) } // Update updates Folder's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.Folder object -func (folder *Folder) Update(body []byte) (FolderResp, error) { +func (folder *Folder) Update(ctx context.Context, body []byte) (FolderResp, error) { body = patchMetadataType(body, "SP.Folder") client := NewHTTPClient(folder.client) - return client.Update(folder.endpoint, bytes.NewBuffer(body), folder.config) + return client.Update(ctx, folder.endpoint, bytes.NewBuffer(body), folder.config) } // Delete deletes this folder (can't be restored from a recycle bin) -func (folder *Folder) Delete() error { +func (folder *Folder) Delete(ctx context.Context) error { client := NewHTTPClient(folder.client) - _, err := client.Delete(folder.endpoint, folder.config) + _, err := client.Delete(ctx, folder.endpoint, folder.config) return err } // Recycle moves this folder to the recycle bin -func (folder *Folder) Recycle() error { +func (folder *Folder) Recycle(ctx context.Context) error { client := NewHTTPClient(folder.client) endpoint := fmt.Sprintf("%s/Recycle", folder.endpoint) - _, err := client.Post(endpoint, nil, folder.config) + _, err := client.Post(ctx, endpoint, nil, folder.config) return err } @@ -121,7 +122,7 @@ func (folder *Folder) Files() *Files { } // ListItemAllFields gets this folder Item data object metadata -func (folder *Folder) ListItemAllFields() (ListItemAllFieldsResp, error) { +func (folder *Folder) ListItemAllFields(ctx context.Context) (ListItemAllFieldsResp, error) { endpoint := fmt.Sprintf("%s/ListItemAllFields", folder.endpoint) apiURL, _ := url.Parse(endpoint) @@ -133,7 +134,7 @@ func (folder *Folder) ListItemAllFields() (ListItemAllFieldsResp, error) { apiURL.RawQuery = query.Encode() client := NewHTTPClient(folder.client) - data, err := client.Get(apiURL.String(), folder.config) + data, err := client.Get(ctx, apiURL.String(), folder.config) if err != nil { return nil, err } @@ -142,9 +143,9 @@ func (folder *Folder) ListItemAllFields() (ListItemAllFieldsResp, error) { } // GetItem gets this folder Item API object metadata -func (folder *Folder) GetItem() (*Item, error) { +func (folder *Folder) GetItem(ctx context.Context) (*Item, error) { scoped := NewFolder(folder.client, folder.endpoint, folder.config) - data, err := scoped.Conf(HeadersPresets.Verbose).Select("Id").ListItemAllFields() + data, err := scoped.Conf(HeadersPresets.Verbose).Select("Id").ListItemAllFields(ctx) if err != nil { return nil, err } @@ -169,8 +170,8 @@ func (folder *Folder) GetItem() (*Item, error) { } // ContextInfo gets current Context Info object data -func (folder *Folder) ContextInfo() (*ContextInfo, error) { - return NewContext(folder.client, folder.ToURL(), folder.config).Get() +func (folder *Folder) ContextInfo(ctx context.Context) (*ContextInfo, error) { + return NewContext(folder.client, folder.ToURL(), folder.config).Get(ctx) } // ToDo: @@ -178,7 +179,7 @@ func (folder *Folder) ContextInfo() (*ContextInfo, error) { // ensureFolder ensures folder existence by its server relative URL // mode: modern (SP 2016 and newer), legacy (SP 2013) -func ensureFolder(web *Web, serverRelativeURL string, currentRelativeURL string, mode string) ([]byte, error) { +func ensureFolder(ctx context.Context, web *Web, serverRelativeURL string, currentRelativeURL string, mode string) ([]byte, error) { headers := map[string]string{} for key, val := range getConfHeaders(web.config) { headers[key] = val @@ -198,7 +199,7 @@ func ensureFolder(web *Web, serverRelativeURL string, currentRelativeURL string, getFolder = web.GetFolder } - data, err := getFolder(currentRelativeURL).Conf(conf).Get() + data, err := getFolder(currentRelativeURL).Conf(conf).Get(ctx) if err != nil { splitted := strings.Split(currentRelativeURL, "/") if len(splitted) == 1 { @@ -206,7 +207,7 @@ func ensureFolder(web *Web, serverRelativeURL string, currentRelativeURL string, } splitted = splitted[0 : len(splitted)-1] currentRelativeURL = strings.Join(splitted, "/") - return ensureFolder(web, serverRelativeURL, currentRelativeURL, mode) + return ensureFolder(ctx, web, serverRelativeURL, currentRelativeURL, mode) } curFolders := strings.Split(currentRelativeURL, "/") @@ -218,7 +219,7 @@ func ensureFolder(web *Web, serverRelativeURL string, currentRelativeURL string, createFolders := expFolders[len(curFolders):] for _, folder := range createFolders { - data, err = getFolder(currentRelativeURL).Folders().Add(url.PathEscape(folder)) + data, err = getFolder(currentRelativeURL).Folders().Add(ctx, url.PathEscape(folder)) if err != nil { return nil, err } diff --git a/api/folder_test.go b/api/folder_test.go index 5032639..9ab90ed 100644 --- a/api/folder_test.go +++ b/api/folder_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" "github.com/google/uuid" @@ -15,13 +16,13 @@ func TestFolder(t *testing.T) { rootFolderURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" t.Run("Add", func(t *testing.T) { - if _, err := web.GetFolder(rootFolderURI).Folders().Add(newFolderName); err != nil { + if _, err := web.GetFolder(rootFolderURI).Folders().Add(context.Background(), newFolderName); err != nil { t.Error(err) } }) t.Run("Get", func(t *testing.T) { - data, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Get() + data, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Get(context.Background()) if err != nil { t.Error(err) } @@ -31,11 +32,11 @@ func TestFolder(t *testing.T) { }) t.Run("GetFolderByID", func(t *testing.T) { - data, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Get() + data, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Get(context.Background()) if err != nil { t.Error(err) } - d, err := web.GetFolderByID(data.Data().UniqueID).Get() + d, err := web.GetFolderByID(data.Data().UniqueID).Get(context.Background()) if err != nil { t.Error(err) } @@ -45,11 +46,11 @@ func TestFolder(t *testing.T) { }) t.Run("GetFolderByPath", func(t *testing.T) { - data, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Get() + data, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Get(context.Background()) if err != nil { t.Error(err) } - d, err := web.GetFolderByPath(data.Data().ServerRelativeURL).Get() + d, err := web.GetFolderByPath(data.Data().ServerRelativeURL).Get(context.Background()) if err != nil { t.Error(err) } @@ -59,13 +60,13 @@ func TestFolder(t *testing.T) { }) t.Run("ContextInfo", func(t *testing.T) { - if _, err := web.GetFolder(rootFolderURI + "/" + newFolderName).ContextInfo(); err != nil { + if _, err := web.GetFolder(rootFolderURI + "/" + newFolderName).ContextInfo(context.Background()); err != nil { t.Error(err) } }) t.Run("ParentFolder", func(t *testing.T) { - pf, err := web.GetFolder(rootFolderURI + "/" + newFolderName).ParentFolder().Get() + pf, err := web.GetFolder(rootFolderURI + "/" + newFolderName).ParentFolder().Get(context.Background()) if err != nil { t.Error(err) } @@ -77,24 +78,24 @@ func TestFolder(t *testing.T) { t.Run("Props", func(t *testing.T) { folder := web.GetFolder(rootFolderURI + "/" + newFolderName) - props, err := folder.Props().Get() + props, err := folder.Props().Get(context.Background()) if err != nil { t.Error(err) } if len(props.Data()) == 0 { t.Error("can't get property bags") } - if err := folder.Props().Set("MyProp", "MyValue"); err != nil { + if err := folder.Props().Set(context.Background(), "MyProp", "MyValue"); err != nil { t.Error("can't set property bags") } }) t.Run("GetItem", func(t *testing.T) { - item, err := web.GetFolder(rootFolderURI + "/" + newFolderName).GetItem() + item, err := web.GetFolder(rootFolderURI + "/" + newFolderName).GetItem(context.Background()) if err != nil { t.Error(err) } - data, err := item.Get() + data, err := item.Get(context.Background()) if err != nil { t.Error(err) } @@ -104,18 +105,18 @@ func TestFolder(t *testing.T) { }) t.Run("Delete", func(t *testing.T) { - if err := web.GetFolder(rootFolderURI + "/" + newFolderName).Delete(); err != nil { + if err := web.GetFolder(rootFolderURI + "/" + newFolderName).Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("Recycle", func(t *testing.T) { guid := uuid.New().String() - fr, err := web.GetFolder(rootFolderURI).Folders().Add(guid) + fr, err := web.GetFolder(rootFolderURI).Folders().Add(context.Background(), guid) if err != nil { t.Error(err) } - if err := web.GetFolder(fr.Data().ServerRelativeURL).Recycle(); err != nil { + if err := web.GetFolder(fr.Data().ServerRelativeURL).Recycle(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/folders.go b/api/folders.go index 561fd12..2ad9c42 100644 --- a/api/folders.go +++ b/api/folders.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "github.com/koltyakov/gosip" @@ -37,16 +38,16 @@ func (folders *Folders) ToURL() string { } // Get gets folders collection response in this folder -func (folders *Folders) Get() (FoldersResp, error) { +func (folders *Folders) Get(ctx context.Context) (FoldersResp, error) { client := NewHTTPClient(folders.client) - return client.Get(folders.ToURL(), folders.config) + return client.Get(ctx, folders.ToURL(), folders.config) } // Add created a folder with specified name in this folder -func (folders *Folders) Add(folderName string) (FolderResp, error) { +func (folders *Folders) Add(ctx context.Context, folderName string) (FolderResp, error) { client := NewHTTPClient(folders.client) endpoint := fmt.Sprintf("%s/Add('%s')", folders.endpoint, folderName) - return client.Post(endpoint, nil, folders.config) + return client.Post(ctx, endpoint, nil, folders.config) } // GetByName gets a folder by its name in this folder diff --git a/api/folders_test.go b/api/folders_test.go index 8a9c92a..9186a51 100644 --- a/api/folders_test.go +++ b/api/folders_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" "github.com/google/uuid" @@ -15,20 +16,20 @@ func TestFolders(t *testing.T) { rootFolderURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" t.Run("Add", func(t *testing.T) { - if _, err := web.GetFolder(rootFolderURI).Folders().Add(newFolderName); err != nil { + if _, err := web.GetFolder(rootFolderURI).Folders().Add(context.Background(), newFolderName); err != nil { t.Error(err) } }) t.Run("Update", func(t *testing.T) { fm := []byte(`{"Name":"Test"}`) - if _, err := web.GetFolder(rootFolderURI + "/" + newFolderName).Update(fm); err != nil { + if _, err := web.GetFolder(rootFolderURI+"/"+newFolderName).Update(context.Background(), fm); err != nil { t.Error(err) } }) t.Run("Get", func(t *testing.T) { - data, err := web.GetFolder(rootFolderURI).Folders().Select("Id").Conf(headers.verbose).Get() + data, err := web.GetFolder(rootFolderURI).Folders().Select("Id").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -41,7 +42,7 @@ func TestFolders(t *testing.T) { }) t.Run("GetByName", func(t *testing.T) { - if _, err := web.GetFolder(rootFolderURI).Folders().GetByName(newFolderName).Get(); err != nil { + if _, err := web.GetFolder(rootFolderURI).Folders().GetByName(newFolderName).Get(context.Background()); err != nil { t.Error(err) } }) @@ -51,7 +52,7 @@ func TestFolders(t *testing.T) { t.Skip("is not supported with legacy SP") } - if _, err := web.GetFolderByPath(rootFolderURI).Get(); err != nil { + if _, err := web.GetFolderByPath(rootFolderURI).Get(context.Background()); err != nil { t.Error(err) } }) @@ -61,17 +62,17 @@ func TestFolders(t *testing.T) { t.Skip("is not supported with legacy SP") } - data, err := web.GetFolder(rootFolderURI).Select("UniqueId").Get() + data, err := web.GetFolder(rootFolderURI).Select("UniqueId").Get(context.Background()) if err != nil { t.Error(err) } - if _, err := web.GetFolderByID(data.Data().UniqueID).Get(); err != nil { + if _, err := web.GetFolderByID(data.Data().UniqueID).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Delete", func(t *testing.T) { - if err := web.GetFolder(rootFolderURI + "/" + newFolderName).Delete(); err != nil { + if err := web.GetFolder(rootFolderURI + "/" + newFolderName).Delete(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/group.go b/api/group.go index 3fb4f1e..0957511 100644 --- a/api/group.go +++ b/api/group.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "net/url" @@ -56,17 +57,17 @@ func (group *Group) ToURL() string { } // Get gets group data object -func (group *Group) Get() (GroupResp, error) { +func (group *Group) Get(ctx context.Context) (GroupResp, error) { client := NewHTTPClient(group.client) - return client.Get(group.ToURL(), group.config) + return client.Get(ctx, group.ToURL(), group.config) } // Update updates Group's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.Group object -func (group *Group) Update(body []byte) (GroupResp, error) { +func (group *Group) Update(ctx context.Context, body []byte) (GroupResp, error) { body = patchMetadataType(body, "SP.Group") client := NewHTTPClient(group.client) - return client.Update(group.endpoint, bytes.NewBuffer(body), group.config) + return client.Update(ctx, group.endpoint, bytes.NewBuffer(body), group.config) } // Users gets Users API queryable collection @@ -79,7 +80,7 @@ func (group *Group) Users() *Users { } // AddUser adds a user by login name to this group -func (group *Group) AddUser(loginName string) error { +func (group *Group) AddUser(ctx context.Context, loginName string) error { endpoint := fmt.Sprintf("%s/Users", group.ToURL()) client := NewHTTPClient(group.client) metadata := make(map[string]interface{}) @@ -88,37 +89,37 @@ func (group *Group) AddUser(loginName string) error { } metadata["LoginName"] = loginName body, _ := json.Marshal(metadata) - _, err := client.Post(endpoint, bytes.NewBuffer(body), group.config) + _, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), group.config) return err } // AddUserByID adds a user by ID to this group -func (group *Group) AddUserByID(userID int) error { +func (group *Group) AddUserByID(ctx context.Context, userID int) error { sp := NewSP(group.client) - user, err := sp.Web().SiteUsers().Select("LoginName").GetByID(userID).Get() + user, err := sp.Web().SiteUsers().Select("LoginName").GetByID(userID).Get(ctx) if err != nil { return err } - return group.AddUser(user.Data().LoginName) + return group.AddUser(ctx, user.Data().LoginName) } // SetUserAsOwner sets a user as owner (available only in SPO) -func (group *Group) SetUserAsOwner(userID int) error { +func (group *Group) SetUserAsOwner(ctx context.Context, userID int) error { endpoint := fmt.Sprintf("%s/SetUserAsOwner(%d)", group.ToURL(), userID) client := NewHTTPClient(group.client) - _, err := client.Post(endpoint, nil, group.config) + _, err := client.Post(ctx, endpoint, nil, group.config) return err } // SetOwner sets a user or group as this group owner -func (group *Group) SetOwner(ownerID int) error { +func (group *Group) SetOwner(ctx context.Context, ownerID int) error { site := NewSite( group.client, fmt.Sprintf("%s/_api/Site", group.client.AuthCnfg.GetSiteURL()), group.config, ) - cg, err := group.Select("Id").Get() + cg, err := group.Select("Id").Get(ctx) if err != nil { return err } @@ -130,7 +131,7 @@ func (group *Group) SetOwner(ownerID int) error { } pType := "group" - pData, err := site.RootWeb().UserInfoList().Items().Expand("ContentType").Filter(fmt.Sprintf("Id eq %d", ownerID)).Get() + pData, err := site.RootWeb().UserInfoList().Items().Expand("ContentType").Filter(fmt.Sprintf("Id eq %d", ownerID)).Get(ctx) if err != nil { return nil } @@ -170,27 +171,27 @@ func (group *Group) SetOwner(ownerID int) error { } client := NewHTTPClient(group.client) - _, err = client.ProcessQuery(group.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), group.config) + _, err = client.ProcessQuery(ctx, group.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), group.config) return err } // RemoveUser removes a user from group -func (group *Group) RemoveUser(loginName string) error { +func (group *Group) RemoveUser(ctx context.Context, loginName string) error { endpoint := fmt.Sprintf( "%s/Users/RemoveByLoginName(@v)?@v='%s'", group.ToURL(), url.QueryEscape(loginName), ) client := NewHTTPClient(group.client) - _, err := client.Post(endpoint, nil, group.config) + _, err := client.Post(ctx, endpoint, nil, group.config) return err } // RemoveUserByID removes a user from group -func (group *Group) RemoveUserByID(userID int) error { +func (group *Group) RemoveUserByID(ctx context.Context, userID int) error { endpoint := fmt.Sprintf("%s/Users/RemoveById(%d)", group.ToURL(), userID) client := NewHTTPClient(group.client) - _, err := client.Post(endpoint, nil, group.config) + _, err := client.Post(ctx, endpoint, nil, group.config) return err } diff --git a/api/group_test.go b/api/group_test.go index d1ebc29..9e5633c 100644 --- a/api/group_test.go +++ b/api/group_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "testing" @@ -16,7 +17,7 @@ func TestGroup(t *testing.T) { newGroupName := uuid.New().String() group := &GroupInfo{} - user, err := web.CurrentUser().Select("Id,LoginName").Get() + user, err := web.CurrentUser().Select("Id,LoginName").Get(context.Background()) if err != nil { t.Error(err) } @@ -28,7 +29,7 @@ func TestGroup(t *testing.T) { } t.Run("Add", func(t *testing.T) { - data, err := web.SiteGroups().Add(newGroupName, nil) + data, err := web.SiteGroups().Add(context.Background(), newGroupName, nil) if err != nil { t.Error(err) } @@ -36,7 +37,7 @@ func TestGroup(t *testing.T) { }) t.Run("Get", func(t *testing.T) { - data, err := web.SiteGroups().GetByName(newGroupName).Get() + data, err := web.SiteGroups().GetByName(newGroupName).Get(context.Background()) if err != nil { t.Error(err) } @@ -52,37 +53,37 @@ func TestGroup(t *testing.T) { } metadata["Description"] = "It's a test group" // ToDo: check if update works body, _ := json.Marshal(metadata) - if _, err := web.SiteGroups().GetByID(group.ID).Update(body); err != nil { + if _, err := web.SiteGroups().GetByID(group.ID).Update(context.Background(), body); err != nil { t.Error(err) } }) t.Run("AddUser", func(t *testing.T) { - if err := web.SiteGroups().GetByID(group.ID).AddUser(user.Data().LoginName); err != nil { + if err := web.SiteGroups().GetByID(group.ID).AddUser(context.Background(), user.Data().LoginName); err != nil { t.Error(err) } }) t.Run("RemoveUser", func(t *testing.T) { - if err := web.SiteGroups().GetByID(group.ID).RemoveUser(user.Data().LoginName); err != nil { + if err := web.SiteGroups().GetByID(group.ID).RemoveUser(context.Background(), user.Data().LoginName); err != nil { t.Error(err) } }) t.Run("AddUserByID", func(t *testing.T) { - if err := web.SiteGroups().GetByID(group.ID).AddUserByID(user.Data().ID); err != nil { + if err := web.SiteGroups().GetByID(group.ID).AddUserByID(context.Background(), user.Data().ID); err != nil { t.Error(err) } }) t.Run("RemoveUserByID", func(t *testing.T) { - if err := web.SiteGroups().GetByID(group.ID).RemoveUserByID(user.Data().ID); err != nil { + if err := web.SiteGroups().GetByID(group.ID).RemoveUserByID(context.Background(), user.Data().ID); err != nil { t.Error(err) } }) t.Run("SetAsOwner/User", func(t *testing.T) { - au, err := web.SiteUsers().Select("Id").Filter(fmt.Sprintf("Id ne %d and PrincipalType eq 1", user.Data().ID)).Top(1).Get() + au, err := web.SiteUsers().Select("Id").Filter(fmt.Sprintf("Id ne %d and PrincipalType eq 1", user.Data().ID)).Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -90,10 +91,10 @@ func TestGroup(t *testing.T) { return } g := web.SiteGroups().GetByID(group.ID) - if err := g.SetOwner(au.Data()[0].Data().ID); err != nil { + if err := g.SetOwner(context.Background(), au.Data()[0].Data().ID); err != nil { t.Error(err) } - o, err := g.Select("Owner/Id").Expand("Owner").Get() + o, err := g.Select("Owner/Id").Expand("Owner").Get(context.Background()) if err != nil { t.Error(err) } @@ -107,15 +108,15 @@ func TestGroup(t *testing.T) { }) t.Run("SetAsOwner/Group", func(t *testing.T) { - mg, err := web.AssociatedGroups().Members().Select("Id").Get() + mg, err := web.AssociatedGroups().Members().Select("Id").Get(context.Background()) if err != nil { t.Error(err) } g := web.SiteGroups().GetByID(group.ID) - if err := g.SetOwner(mg.Data().ID); err != nil { + if err := g.SetOwner(context.Background(), mg.Data().ID); err != nil { t.Error(err) } - o, err := g.Select("Owner/Id").Expand("Owner").Get() + o, err := g.Select("Owner/Id").Expand("Owner").Get(context.Background()) if err != nil { t.Error(err) } @@ -133,7 +134,7 @@ func TestGroup(t *testing.T) { t.Skip("is not supported with SP 2013") } - au, err := web.SiteUsers().Select("Id").Filter(fmt.Sprintf("Id ne %d", user.Data().ID)).OrderBy("Id", false).Top(1).Get() + au, err := web.SiteUsers().Select("Id").Filter(fmt.Sprintf("Id ne %d", user.Data().ID)).OrderBy("Id", false).Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -141,19 +142,19 @@ func TestGroup(t *testing.T) { return } g := web.SiteGroups().GetByID(group.ID) - if err := g.SetUserAsOwner(au.Data()[0].Data().ID); err != nil { + if err := g.SetUserAsOwner(context.Background(), au.Data()[0].Data().ID); err != nil { t.Error(err) } }) t.Run("RemoveByID", func(t *testing.T) { - if err := web.SiteGroups().RemoveByID(group.ID); err != nil { + if err := web.SiteGroups().RemoveByID(context.Background(), group.ID); err != nil { t.Error(err) } }) t.Run("Modifiers", func(t *testing.T) { - if _, err := web.AssociatedGroups().Visitors().Users().Get(); err != nil { + if _, err := web.AssociatedGroups().Visitors().Users().Get(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/groups.go b/api/groups.go index ad0f7eb..efcea9c 100644 --- a/api/groups.go +++ b/api/groups.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -38,14 +39,14 @@ func (groups *Groups) ToURL() string { } // Get gets site Groups response - a collection of GroupInfo -func (groups *Groups) Get() (GroupsResp, error) { +func (groups *Groups) Get(ctx context.Context) (GroupsResp, error) { client := NewHTTPClient(groups.client) - return client.Get(groups.ToURL(), groups.config) + return client.Get(ctx, groups.ToURL(), groups.config) } // Add creates new group with a specified name. Additional metadata can optionally be provided as string map object. // `metadata` should correspond to SP.Group type. -func (groups *Groups) Add(title string, metadata map[string]interface{}) (GroupResp, error) { +func (groups *Groups) Add(ctx context.Context, title string, metadata map[string]interface{}) (GroupResp, error) { if metadata == nil { metadata = make(map[string]interface{}) } @@ -55,7 +56,7 @@ func (groups *Groups) Add(title string, metadata map[string]interface{}) (GroupR metadata["Title"] = title body, _ := json.Marshal(metadata) client := NewHTTPClient(groups.client) - return client.Post(groups.endpoint, bytes.NewBuffer(body), groups.config) + return client.Post(ctx, groups.endpoint, bytes.NewBuffer(body), groups.config) } // GetByID gets a group object by its ID @@ -77,21 +78,21 @@ func (groups *Groups) GetByName(groupName string) *Group { } // RemoveByID deletes a group object by its ID -func (groups *Groups) RemoveByID(groupID int) error { +func (groups *Groups) RemoveByID(ctx context.Context, groupID int) error { endpoint := fmt.Sprintf("%s/RemoveById(%d)", groups.ToURL(), groupID) client := NewHTTPClient(groups.client) - _, err := client.Post(endpoint, nil, groups.config) + _, err := client.Post(ctx, endpoint, nil, groups.config) return err } // RemoveByLoginName deletes a group object by its login name -func (groups *Groups) RemoveByLoginName(loginName string) error { +func (groups *Groups) RemoveByLoginName(ctx context.Context, loginName string) error { endpoint := fmt.Sprintf( "%s/RemoveByLoginName('%s')", groups.endpoint, loginName, // url.QueryEscape(loginName), ) client := NewHTTPClient(groups.client) - _, err := client.Post(endpoint, nil, groups.config) + _, err := client.Post(ctx, endpoint, nil, groups.config) return err } diff --git a/api/groups_test.go b/api/groups_test.go index b891372..d5b405b 100644 --- a/api/groups_test.go +++ b/api/groups_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" "github.com/google/uuid" @@ -18,7 +19,7 @@ func TestGroups(t *testing.T) { t.Run("Constructor", func(t *testing.T) { g := NewGroups(spClient, endpoint, nil) - if _, err := g.Select("Id").Get(); err != nil { + if _, err := g.Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) @@ -34,7 +35,7 @@ func TestGroups(t *testing.T) { }) t.Run("GetGroups", func(t *testing.T) { - data, err := groups.Select("Id").Top(5).Get() + data, err := groups.Select("Id").Top(5).Get(context.Background()) if err != nil { t.Error(err) } @@ -44,7 +45,7 @@ func TestGroups(t *testing.T) { }) t.Run("GetGroup", func(t *testing.T) { - data, err := groups.Select("Id,Title").Top(1).Get() + data, err := groups.Select("Id,Title").Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -60,13 +61,13 @@ func TestGroups(t *testing.T) { }) t.Run("GetByID", func(t *testing.T) { - data0, err := groups.Select("Id,Title").Top(1).Get() + data0, err := groups.Select("Id,Title").Top(1).Get(context.Background()) if err != nil { t.Error(err) } groupID := data0.Data()[0].Data().ID - data, err := groups.GetByID(groupID).Select("Id").Get() + data, err := groups.GetByID(groupID).Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -81,13 +82,13 @@ func TestGroups(t *testing.T) { }) t.Run("GetByName", func(t *testing.T) { - data0, err := groups.Select("Id,Title").Top(1).Get() + data0, err := groups.Select("Id,Title").Top(1).Get(context.Background()) if err != nil { t.Error(err) } groupTitle := data0.Data()[0].Data().Title - data, err := groups.GetByName(groupTitle).Select("Title").Get() + data, err := groups.GetByName(groupTitle).Select("Title").Get(context.Background()) if err != nil { t.Error(err) } @@ -102,11 +103,11 @@ func TestGroups(t *testing.T) { }) t.Run("Add", func(t *testing.T) { - if _, err := groups.Conf(headers.verbose).Add(newGroupName, nil); err != nil { + if _, err := groups.Conf(headers.verbose).Add(context.Background(), newGroupName, nil); err != nil { t.Error(err) } - u, err := sp.Web().CurrentUser().Select("Id").Get() + u, err := sp.Web().CurrentUser().Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -114,21 +115,21 @@ func TestGroups(t *testing.T) { if envCode != "spo" { t.Skip("is not supported with legacy SP") } - if err := groups.GetByName(newGroupName).SetOwner(u.Data().ID); err != nil { + if err := groups.GetByName(newGroupName).SetOwner(context.Background(), u.Data().ID); err != nil { t.Error(err) } }) t.Run("RemoveByLoginName", func(t *testing.T) { - if _, err := groups.Conf(headers.verbose).Add(newGroupNameRemove, nil); err != nil { + if _, err := groups.Conf(headers.verbose).Add(context.Background(), newGroupNameRemove, nil); err != nil { t.Error(err) } - if err := groups.RemoveByLoginName(newGroupNameRemove); err != nil { + if err := groups.RemoveByLoginName(context.Background(), newGroupNameRemove); err != nil { t.Error(err) } }) - if err := groups.RemoveByLoginName(newGroupName); err != nil { + if err := groups.RemoveByLoginName(context.Background(), newGroupName); err != nil { t.Error(err) } diff --git a/api/http.go b/api/http.go index 5e54989..acbe895 100644 --- a/api/http.go +++ b/api/http.go @@ -58,8 +58,8 @@ func NewHTTPClient(spClient *gosip.SPClient) *HTTPClient { } // Get - generic GET request wrapper -func (client *HTTPClient) Get(endpoint string, conf *RequestConfig) ([]byte, error) { - req, err := http.NewRequest("GET", endpoint, nil) +func (client *HTTPClient) Get(ctx context.Context, endpoint string, conf *RequestConfig) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil) if err != nil { return nil, fmt.Errorf("unable to create a request: %w", err) } @@ -89,9 +89,9 @@ func (client *HTTPClient) Get(endpoint string, conf *RequestConfig) ([]byte, err } // Post - generic POST request wrapper -func (client *HTTPClient) Post(endpoint string, body io.Reader, conf *RequestConfig) ([]byte, error) { +func (client *HTTPClient) Post(ctx context.Context, endpoint string, body io.Reader, conf *RequestConfig) ([]byte, error) { // req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(body)) - req, err := http.NewRequest("POST", endpoint, body) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, body) if err != nil { return nil, fmt.Errorf("unable to create a request: %w", err) } @@ -122,8 +122,8 @@ func (client *HTTPClient) Post(endpoint string, body io.Reader, conf *RequestCon } // Delete - generic DELETE request wrapper -func (client *HTTPClient) Delete(endpoint string, conf *RequestConfig) ([]byte, error) { - req, err := http.NewRequest("POST", endpoint, nil) +func (client *HTTPClient) Delete(ctx context.Context, endpoint string, conf *RequestConfig) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, nil) if err != nil { return nil, fmt.Errorf("unable to create a request: %w", err) } @@ -156,9 +156,9 @@ func (client *HTTPClient) Delete(endpoint string, conf *RequestConfig) ([]byte, } // Update - generic MERGE request wrapper -func (client *HTTPClient) Update(endpoint string, body io.Reader, conf *RequestConfig) ([]byte, error) { +func (client *HTTPClient) Update(ctx context.Context, endpoint string, body io.Reader, conf *RequestConfig) ([]byte, error) { // req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(body)) - req, err := http.NewRequest("POST", endpoint, body) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, body) if err != nil { return nil, fmt.Errorf("unable to create a request: %w", err) } @@ -191,13 +191,13 @@ func (client *HTTPClient) Update(endpoint string, body io.Reader, conf *RequestC } // ProcessQuery - CSOM requests helper -func (client *HTTPClient) ProcessQuery(endpoint string, body io.Reader, conf *RequestConfig) ([]byte, error) { +func (client *HTTPClient) ProcessQuery(ctx context.Context, endpoint string, body io.Reader, conf *RequestConfig) ([]byte, error) { if !strings.Contains(strings.ToLower(endpoint), strings.ToLower("/_vti_bin/client.svc/ProcessQuery")) { endpoint = fmt.Sprintf("%s/_vti_bin/client.svc/ProcessQuery", getPriorEndpoint(endpoint, "/_api")) } // req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(body)) - req, err := http.NewRequest("POST", endpoint, body) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, body) if err != nil { return nil, fmt.Errorf("unable to create a request: %w", err) } diff --git a/api/http_retry_test.go b/api/http_retry_test.go index a5f43f6..7809c4b 100644 --- a/api/http_retry_test.go +++ b/api/http_retry_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" "github.com/google/uuid" @@ -13,7 +14,7 @@ func TestHttpRetry(t *testing.T) { t.Run("ShouldForceRetry", func(t *testing.T) { guid := uuid.New().String() - if _, err := sp.Web().GetFolder("Shared Documents/" + guid).Folders().Add("123"); err == nil { + if _, err := sp.Web().GetFolder("Shared Documents/"+guid).Folders().Add(context.Background(), "123"); err == nil { t.Error("should not succeeded, but force a retries") } }) diff --git a/api/http_test.go b/api/http_test.go index 9db7b91..3e48913 100644 --- a/api/http_test.go +++ b/api/http_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "strings" "testing" ) @@ -26,7 +27,7 @@ func TestHttp(t *testing.T) { `)) - if _, err := client.ProcessQuery(spClient.AuthCnfg.GetSiteURL(), bytes.NewBuffer(body), nil); err != nil { + if _, err := client.ProcessQuery(context.Background(), spClient.AuthCnfg.GetSiteURL(), bytes.NewBuffer(body), nil); err != nil { if !strings.Contains(err.Error(), "Microsoft.SharePoint.Client.InvalidClientQueryException") { t.Error(err) } diff --git a/api/item.go b/api/item.go index f75eda3..1c3d1ad 100644 --- a/api/item.go +++ b/api/item.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "strings" @@ -55,28 +56,28 @@ func (item *Item) ToURL() string { } // Get gets this Item info -func (item *Item) Get() (ItemResp, error) { +func (item *Item) Get(ctx context.Context) (ItemResp, error) { client := NewHTTPClient(item.client) - return client.Get(item.ToURL(), item.config) + return client.Get(ctx, item.ToURL(), item.config) } // Delete deletes this Item (can't be restored from a recycle bin) -func (item *Item) Delete() error { +func (item *Item) Delete(ctx context.Context) error { client := NewHTTPClient(item.client) - _, err := client.Delete(item.endpoint, item.config) + _, err := client.Delete(ctx, item.endpoint, item.config) return err } // Recycle moves this item to the recycle bin -func (item *Item) Recycle() error { +func (item *Item) Recycle(ctx context.Context) error { endpoint := fmt.Sprintf("%s/Recycle", item.endpoint) client := NewHTTPClient(item.client) - _, err := client.Post(endpoint, nil, item.config) + _, err := client.Post(ctx, endpoint, nil, item.config) return err } // Update updates item's metadata. `body` parameter is byte array representation of JSON string payload relevant to item metadata object. -func (item *Item) Update(body []byte) (ItemResp, error) { +func (item *Item) Update(ctx context.Context, body []byte) (ItemResp, error) { body = patchMetadataTypeCB(body, func() string { endpoint := getPriorEndpoint(item.endpoint, "/Items") cacheKey := strings.ToLower(endpoint + "@entitytype") @@ -84,12 +85,12 @@ func (item *Item) Update(body []byte) (ItemResp, error) { return oDataType.(string) } list := NewList(item.client, endpoint, nil) - oDataType, _ := list.GetEntityType() + oDataType, _ := list.GetEntityType(ctx) storage.Set(cacheKey, oDataType, 0) return oDataType }) client := NewHTTPClient(item.client) - return client.Update(item.endpoint, bytes.NewBuffer(body), item.config) + return client.Update(ctx, item.endpoint, bytes.NewBuffer(body), item.config) } // Roles gets Roles API instance queryable collection for this Item @@ -121,8 +122,8 @@ func (item *Item) Records() *Records { } // ContextInfo gets current context information -func (item *Item) ContextInfo() (*ContextInfo, error) { - return NewContext(item.client, item.ToURL(), item.config).Get() +func (item *Item) ContextInfo(ctx context.Context) (*ContextInfo, error) { + return NewContext(item.client, item.ToURL(), item.config).Get(ctx) } /* Response helpers */ diff --git a/api/item_test.go b/api/item_test.go index 98a3a2e..62bb3df 100644 --- a/api/item_test.go +++ b/api/item_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "testing" @@ -14,11 +15,11 @@ func TestItem(t *testing.T) { web := NewSP(spClient).Web() newListTitle := uuid.New().String() - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } list := web.Lists().GetByTitle(newListTitle) - entType, err := list.GetEntityType() + entType, err := list.GetEntityType(context.Background()) if err != nil { t.Error(err) } @@ -29,14 +30,14 @@ func TestItem(t *testing.T) { metadata["__metadata"] = map[string]string{"type": entType} metadata["Title"] = fmt.Sprintf("Item %d", i) body, _ := json.Marshal(metadata) - if _, err := list.Items().Add(body); err != nil { + if _, err := list.Items().Add(context.Background(), body); err != nil { t.Error(err) } } }) t.Run("Get", func(t *testing.T) { - item, err := list.Items().GetByID(1).Conf(HeadersPresets.Verbose).Get() + item, err := list.Items().GetByID(1).Conf(HeadersPresets.Verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -56,7 +57,7 @@ func TestItem(t *testing.T) { metadata["__metadata"] = map[string]string{"type": entType} metadata["Title"] = "Updated Item 1" body, _ := json.Marshal(metadata) - if _, err := list.Items().GetByID(1).Update(body); err != nil { + if _, err := list.Items().GetByID(1).Update(context.Background(), body); err != nil { t.Error(err) } }) @@ -65,42 +66,42 @@ func TestItem(t *testing.T) { metadata := make(map[string]interface{}) metadata["Title"] = "Updated Item 2" body, _ := json.Marshal(metadata) - if _, err := list.Items().GetByID(2).Update(body); err != nil { + if _, err := list.Items().GetByID(2).Update(context.Background(), body); err != nil { t.Error(err) } }) t.Run("Delete", func(t *testing.T) { - if err := list.Items().GetByID(1).Delete(); err != nil { + if err := list.Items().GetByID(1).Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("Recycle", func(t *testing.T) { - if err := list.Items().GetByID(2).Recycle(); err != nil { + if err := list.Items().GetByID(2).Recycle(context.Background()); err != nil { t.Error(err) } }) t.Run("ParentList", func(t *testing.T) { - if _, err := list.Items().GetByID(3).ParentList().Get(); err != nil { + if _, err := list.Items().GetByID(3).ParentList().Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Roles", func(t *testing.T) { - if _, err := list.Items().GetByID(3).Roles().HasUniqueAssignments(); err != nil { + if _, err := list.Items().GetByID(3).Roles().HasUniqueAssignments(context.Background()); err != nil { t.Error(err) } }) t.Run("ContextInfo", func(t *testing.T) { - if _, err := list.Items().GetByID(3).ContextInfo(); err != nil { + if _, err := list.Items().GetByID(3).ContextInfo(context.Background()); err != nil { t.Error(err) } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } } diff --git a/api/items.go b/api/items.go index 53ee396..ef8e44c 100644 --- a/api/items.go +++ b/api/items.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "net/url" @@ -41,9 +42,9 @@ func (items *Items) ToURL() string { } // Get gets Items API queryable collection -func (items *Items) Get() (ItemsResp, error) { +func (items *Items) Get(ctx context.Context) (ItemsResp, error) { client := NewHTTPClient(items.client) - data, err := client.Get(items.ToURL(), items.config) + data, err := client.Get(ctx, items.ToURL(), items.config) if err != nil { return nil, err } @@ -52,12 +53,12 @@ func (items *Items) Get() (ItemsResp, error) { // GetAll gets all items in a list using internal page helper. The use case of the method is getting all the content from large lists. // Method ignores custom sorting and filtering as not supported for the large lists due to throttling limitations. -func (items *Items) GetAll() ([]ItemResp, error) { - return getAll(nil, nil, items) +func (items *Items) GetAll(ctx context.Context) ([]ItemResp, error) { + return getAll(ctx, nil, nil, items) } // Add adds new item in this list. `body` parameter is byte array representation of JSON string payload relevant to item metadata object. -func (items *Items) Add(body []byte) (ItemResp, error) { +func (items *Items) Add(ctx context.Context, body []byte) (ItemResp, error) { body = patchMetadataTypeCB(body, func() string { endpoint := getPriorEndpoint(items.endpoint, "/Items") cacheKey := strings.ToLower(endpoint + "@entitytype") @@ -65,12 +66,12 @@ func (items *Items) Add(body []byte) (ItemResp, error) { return oDataType.(string) } list := NewList(items.client, endpoint, nil) - oDataType, _ := list.GetEntityType() + oDataType, _ := list.GetEntityType(ctx) storage.Set(cacheKey, oDataType, 0) return oDataType }) client := NewHTTPClient(items.client) - return client.Post(items.endpoint, bytes.NewBuffer(body), items.config) + return client.Post(ctx, items.endpoint, bytes.NewBuffer(body), items.config) } // GetByID gets item data object by its ID @@ -83,7 +84,7 @@ func (items *Items) GetByID(itemID int) *Item { } // GetByCAML gets items data using CAML query -func (items *Items) GetByCAML(caml string) (ItemsResp, error) { +func (items *Items) GetByCAML(ctx context.Context, caml string) (ItemsResp, error) { endpoint := fmt.Sprintf("%s/GetItems", strings.TrimRight(items.endpoint, "/Items")) apiURL, _ := url.Parse(endpoint) query := url.Values{} @@ -107,7 +108,7 @@ func (items *Items) GetByCAML(caml string) (ItemsResp, error) { body, _ := json.Marshal(request) client := NewHTTPClient(items.client) - return client.Post(apiURL.String(), bytes.NewBuffer(body), items.config) + return client.Post(ctx, apiURL.String(), bytes.NewBuffer(body), items.config) } // ToDo: @@ -115,7 +116,7 @@ func (items *Items) GetByCAML(caml string) (ItemsResp, error) { // Helper methods -func getAll(res []ItemResp, cur ItemsResp, items *Items) ([]ItemResp, error) { +func getAll(ctx context.Context, res []ItemResp, cur ItemsResp, items *Items) ([]ItemResp, error) { if res == nil && cur == nil { itemsCopy := NewItems(items.client, items.endpoint, items.config) for key, val := range items.modifiers.Get() { @@ -129,7 +130,7 @@ func getAll(res []ItemResp, cur ItemsResp, items *Items) ([]ItemResp, error) { itemsCopy.modifiers.AddTop(top) } } - itemsResp, err := itemsCopy.Get() + itemsResp, err := itemsCopy.Get(ctx) if err != nil { return nil, err } @@ -140,12 +141,12 @@ func getAll(res []ItemResp, cur ItemsResp, items *Items) ([]ItemResp, error) { if nextURL == "" { return res, nil } - nextItemsResp, err := NewItems(items.client, nextURL, items.config).Get() + nextItemsResp, err := NewItems(items.client, nextURL, items.config).Get(ctx) if err != nil { return res, err } res = append(res, nextItemsResp.Data()...) - return getAll(res, nextItemsResp, items) + return getAll(ctx, res, nextItemsResp, items) } /* Pagination helpers */ @@ -158,8 +159,8 @@ type ItemsPage struct { } // GetPaged gets Paged Items collection -func (items *Items) GetPaged() (*ItemsPage, error) { - data, err := items.Get() +func (items *Items) GetPaged(ctx context.Context) (*ItemsPage, error) { + data, err := items.Get(ctx) if err != nil { return nil, err } @@ -173,7 +174,7 @@ func (items *Items) GetPaged() (*ItemsPage, error) { if nextURL == "" { return nil, fmt.Errorf("unable to get next page") } - return NewItems(items.client, nextURL, items.config).GetPaged() + return NewItems(items.client, nextURL, items.config).GetPaged(ctx) }, } return res, nil diff --git a/api/items_paged_test.go b/api/items_paged_test.go index 4a4569a..b9503a5 100644 --- a/api/items_paged_test.go +++ b/api/items_paged_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "sync" @@ -14,11 +15,11 @@ func TestItemsPaged(t *testing.T) { web := NewSP(spClient).Web() newListTitle := uuid.New().String() - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } list := web.Lists().GetByTitle(newListTitle) - entType, err := list.GetEntityType() + entType, err := list.GetEntityType(context.Background()) if err != nil { t.Error(err) } @@ -32,7 +33,7 @@ func TestItemsPaged(t *testing.T) { metadata["__metadata"] = map[string]string{"type": entType} metadata["Title"] = fmt.Sprintf("Item %d", i) body, _ := json.Marshal(metadata) - if _, err := list.Items().Add(body); err != nil { + if _, err := list.Items().Add(context.Background(), body); err != nil { t.Error(err) } wg.Done() @@ -42,7 +43,7 @@ func TestItemsPaged(t *testing.T) { }) t.Run("HasNextPage", func(t *testing.T) { - items, err := list.Items().Select("Id").Top(1).Get() + items, err := list.Items().Select("Id").Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -54,7 +55,7 @@ func TestItemsPaged(t *testing.T) { t.Skip("is not supported with SP 2013") } - items, err = list.Items().Conf(HeadersPresets.Minimalmetadata).Select("Id").Top(1).Get() + items, err = list.Items().Conf(HeadersPresets.Minimalmetadata).Select("Id").Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -62,7 +63,7 @@ func TestItemsPaged(t *testing.T) { t.Error("can't get next page URL") } - items, err = list.Items().Conf(HeadersPresets.Nometadata).Select("Id").Top(1).Get() + items, err = list.Items().Conf(HeadersPresets.Nometadata).Select("Id").Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -72,7 +73,7 @@ func TestItemsPaged(t *testing.T) { }) t.Run("GetAll", func(t *testing.T) { - items, err := list.Items().Select("Id").Top(10).GetAll() + items, err := list.Items().Select("Id").Top(10).GetAll(context.Background()) if err != nil { t.Error(err) } @@ -81,7 +82,7 @@ func TestItemsPaged(t *testing.T) { } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/items_test.go b/api/items_test.go index 78bfa09..4f62c97 100644 --- a/api/items_test.go +++ b/api/items_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "strings" @@ -15,25 +16,25 @@ func TestItems(t *testing.T) { web := NewSP(spClient).Web() newListTitle := strings.Replace(uuid.New().String(), "-", "", -1) - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } list := web.Lists().GetByTitle(newListTitle) - entType, err := list.GetEntityType() + entType, err := list.GetEntityType(context.Background()) if err != nil { t.Error(err) } t.Run("AddWithoutMetadataType", func(t *testing.T) { body := []byte(`{"Title":"Item"}`) - if _, err := list.Items().Add(body); err != nil { + if _, err := list.Items().Add(context.Background(), body); err != nil { t.Error(err) } }) t.Run("AddResponse", func(t *testing.T) { body := []byte(`{"Title":"Item"}`) - item, err := list.Items().Add(body) + item, err := list.Items().Add(context.Background(), body) if err != nil { t.Error(err) } @@ -48,14 +49,14 @@ func TestItems(t *testing.T) { metadata["__metadata"] = map[string]string{"type": entType} metadata["Title"] = fmt.Sprintf("Item %d", i) body, _ := json.Marshal(metadata) - if _, err := list.Items().Add(body); err != nil { + if _, err := list.Items().Add(context.Background(), body); err != nil { t.Error(err) } } }) t.Run("Get", func(t *testing.T) { - items, err := list.Items().Top(100).OrderBy("Title", false).Get() + items, err := list.Items().Top(100).OrderBy("Title", false).Get(context.Background()) if err != nil { t.Error(err) } @@ -77,7 +78,7 @@ func TestItems(t *testing.T) { }) t.Run("GetPaged", func(t *testing.T) { - paged, err := list.Items().Top(5).GetPaged() + paged, err := list.Items().Top(5).GetPaged(context.Background()) if err != nil { t.Error(err) } @@ -94,7 +95,7 @@ func TestItems(t *testing.T) { }) t.Run("GetByID", func(t *testing.T) { - item, err := list.Items().GetByID(1).Get() + item, err := list.Items().GetByID(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -104,7 +105,7 @@ func TestItems(t *testing.T) { }) t.Run("Get/Unmarshal", func(t *testing.T) { - item, err := list.Items().GetByID(1).Get() + item, err := list.Items().GetByID(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -129,7 +130,7 @@ func TestItems(t *testing.T) { ` - data, err := list.Items().Select("Id").GetByCAML(caml) + data, err := list.Items().Select("Id").GetByCAML(context.Background(), caml) if err != nil { t.Error(err) } @@ -142,16 +143,16 @@ func TestItems(t *testing.T) { }) t.Run("GetByCAMLAdvanced", func(t *testing.T) { - viewResp, err := list.Views().DefaultView().Select("ListViewXml").Get() + viewResp, err := list.Views().DefaultView().Select("ListViewXml").Get(context.Background()) if err != nil { t.Error(err) } - if _, err := list.Items().GetByCAML(viewResp.Data().ListViewXML); err != nil { + if _, err := list.Items().GetByCAML(context.Background(), viewResp.Data().ListViewXML); err != nil { t.Error(err) } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/items_vadd.go b/api/items_vadd.go index 0d7e9e3..0bd2ce4 100644 --- a/api/items_vadd.go +++ b/api/items_vadd.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "strconv" @@ -29,7 +30,7 @@ type AddValidateFieldResult struct { // AddValidate adds new item in this list using AddValidateUpdateItemUsingPath method. // formValues fingerprints https://github.com/koltyakov/sp-sig-20180705-demo/blob/master/src/03-pnp/FieldTypes.md#field-data-types-fingerprints-sample -func (items *Items) AddValidate(formValues map[string]string, options *ValidateAddOptions) (AddValidateResp, error) { +func (items *Items) AddValidate(ctx context.Context, formValues map[string]string, options *ValidateAddOptions) (AddValidateResp, error) { endpoint := fmt.Sprintf("%s/AddValidateUpdateItemUsingPath()", getPriorEndpoint(items.endpoint, "/items")) client := NewHTTPClient(items.client) type formValue struct { @@ -62,7 +63,7 @@ func (items *Items) AddValidate(formValues map[string]string, options *ValidateA var res AddValidateResp var err error - res, err = client.Post(endpoint, bytes.NewBuffer(body), items.config) + res, err = client.Post(ctx, endpoint, bytes.NewBuffer(body), items.config) if err != nil { return res, err } diff --git a/api/items_vadd_test.go b/api/items_vadd_test.go index 9997bc4..6292036 100644 --- a/api/items_vadd_test.go +++ b/api/items_vadd_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "strings" "testing" @@ -12,7 +13,7 @@ func TestItemsVAdd(t *testing.T) { web := NewSP(spClient).Web() newListTitle := strings.Replace(uuid.New().String(), "-", "", -1) - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } list := web.Lists().GetByTitle(newListTitle) @@ -24,7 +25,7 @@ func TestItemsVAdd(t *testing.T) { options := &ValidateAddOptions{NewDocumentUpdate: true, CheckInComment: "test"} data := map[string]string{"Title": "New item"} - res, err := list.Items().AddValidate(data, options) + res, err := list.Items().AddValidate(context.Background(), data, options) if err != nil { t.Error(err) } @@ -45,7 +46,7 @@ func TestItemsVAdd(t *testing.T) { options := &ValidateAddOptions{NewDocumentUpdate: true, CheckInComment: "test"} data := map[string]string{"Modified": "wrong"} - if _, err := list.Items().AddValidate(data, options); err == nil { + if _, err := list.Items().AddValidate(context.Background(), data, options); err == nil { t.Error("failed to detect wrong payload") } }) @@ -61,10 +62,10 @@ func TestItemsVAdd(t *testing.T) { folderName := "subfolder" - if _, err := list.Update([]byte(`{ "EnableFolderCreation": true }`)); err != nil { + if _, err := list.Update(context.Background(), []byte(`{ "EnableFolderCreation": true }`)); err != nil { t.Error(err) } - ff, err := list.Items().AddValidate(map[string]string{ + ff, err := list.Items().AddValidate(context.Background(), map[string]string{ "Title": folderName, "FileLeafRef": folderName, "ContentType": "Folder", @@ -73,19 +74,19 @@ func TestItemsVAdd(t *testing.T) { if err != nil { t.Error(err) } - if _, err := list.Items().GetByID(ff.ID()).Update([]byte(`{ "FileLeafRef": "` + folderName + `" }`)); err != nil { + if _, err := list.Items().GetByID(ff.ID()).Update(context.Background(), []byte(`{ "FileLeafRef": "`+folderName+`" }`)); err != nil { t.Error(err) } options := &ValidateAddOptions{NewDocumentUpdate: true, CheckInComment: "test"} options.DecodedPath = "Lists/" + newListTitle + "/" + folderName data := map[string]string{"Title": "New item in folder"} - if _, err := list.Items().AddValidate(data, options); err != nil { + if _, err := list.Items().AddValidate(context.Background(), data, options); err != nil { t.Error(err) } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/items_vupd.go b/api/items_vupd.go index 91e15fc..98923da 100644 --- a/api/items_vupd.go +++ b/api/items_vupd.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" ) @@ -27,7 +28,7 @@ type UpdateValidateFieldResult struct { // UpdateValidate updates an item in this list using ValidateUpdateListItem method. // formValues fingerprints https://github.com/koltyakov/sp-sig-20180705-demo/blob/master/src/03-pnp/FieldTypes.md#field-data-types-fingerprints-sample -func (item *Item) UpdateValidate(formValues map[string]string, options *ValidateUpdateOptions) (UpdateValidateResp, error) { +func (item *Item) UpdateValidate(ctx context.Context, formValues map[string]string, options *ValidateUpdateOptions) (UpdateValidateResp, error) { endpoint := fmt.Sprintf("%s/ValidateUpdateListItem", item.endpoint) client := NewHTTPClient(item.client) type formValue struct { @@ -51,7 +52,7 @@ func (item *Item) UpdateValidate(formValues map[string]string, options *Validate var res UpdateValidateResp var err error - res, err = client.Post(endpoint, bytes.NewBuffer(body), item.config) + res, err = client.Post(ctx, endpoint, bytes.NewBuffer(body), item.config) if err != nil { return res, err } diff --git a/api/items_vupd_test.go b/api/items_vupd_test.go index 14a443a..f7e6412 100644 --- a/api/items_vupd_test.go +++ b/api/items_vupd_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "strings" "testing" @@ -12,20 +13,20 @@ func TestItemsVUpd(t *testing.T) { web := NewSP(spClient).Web() newListTitle := strings.Replace(uuid.New().String(), "-", "", -1) - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } list := web.Lists().GetByTitle(newListTitle) t.Run("UpdateValidate", func(t *testing.T) { - i, err := list.Items().Add([]byte(`{"Title":"Item"}`)) + i, err := list.Items().Add(context.Background(), []byte(`{"Title":"Item"}`)) if err != nil { t.Error(err) } options := &ValidateUpdateOptions{NewDocumentUpdate: true, CheckInComment: "test"} data := map[string]string{"Title": "New item"} - res, err := list.Items().GetByID(i.Data().ID).UpdateValidate(data, options) + res, err := list.Items().GetByID(i.Data().ID).UpdateValidate(context.Background(), data, options) if err != nil { t.Error(err) } @@ -36,19 +37,19 @@ func TestItemsVUpd(t *testing.T) { }) t.Run("UpdateValidateWrongPayload", func(t *testing.T) { - i, err := list.Items().Add([]byte(`{"Title":"Item"}`)) + i, err := list.Items().Add(context.Background(), []byte(`{"Title":"Item"}`)) if err != nil { t.Error(err) } options := &ValidateUpdateOptions{NewDocumentUpdate: true, CheckInComment: "test"} data := map[string]string{"Modified": "wrong"} - if _, err := list.Items().GetByID(i.Data().ID).UpdateValidate(data, options); err == nil { + if _, err := list.Items().GetByID(i.Data().ID).UpdateValidate(context.Background(), data, options); err == nil { t.Error("failed to detect wrong payload") } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/list.go b/api/list.go index d7b62d0..8db0f74 100644 --- a/api/list.go +++ b/api/list.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "net/url" @@ -111,32 +112,32 @@ func (list *List) ToURL() string { } // Get gets list's data object -func (list *List) Get() (ListResp, error) { +func (list *List) Get(ctx context.Context) (ListResp, error) { client := NewHTTPClient(list.client) - return client.Get(list.ToURL(), list.config) + return client.Get(ctx, list.ToURL(), list.config) } // Delete deletes a list (can't be restored from a recycle bin) -func (list *List) Delete() error { +func (list *List) Delete(ctx context.Context) error { client := NewHTTPClient(list.client) - _, err := client.Delete(list.endpoint, list.config) + _, err := client.Delete(ctx, list.endpoint, list.config) return err } // Recycle moves this list to the recycle bin -func (list *List) Recycle() error { +func (list *List) Recycle(ctx context.Context) error { endpoint := fmt.Sprintf("%s/Recycle", list.endpoint) client := NewHTTPClient(list.client) - _, err := client.Post(endpoint, nil, list.config) + _, err := client.Post(ctx, endpoint, nil, list.config) return err } // Update updates List's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.List object -func (list *List) Update(body []byte) (ListResp, error) { +func (list *List) Update(ctx context.Context, body []byte) (ListResp, error) { body = patchMetadataType(body, "SP.List") client := NewHTTPClient(list.client) - return client.Update(list.endpoint, bytes.NewBuffer(body), list.config) + return client.Update(ctx, list.endpoint, bytes.NewBuffer(body), list.config) } // Items gets Items API instance queryable collection @@ -213,9 +214,9 @@ func (list *List) RootFolder() *Folder { } // GetEntityType gets list's ListItemEntityTypeFullName -func (list *List) GetEntityType() (string, error) { +func (list *List) GetEntityType(ctx context.Context) (string, error) { scoped := NewList(list.client, list.endpoint, list.config) - data, err := scoped.Select("ListItemEntityTypeFullName").Get() + data, err := scoped.Select("ListItemEntityTypeFullName").Get(ctx) if err != nil { return "", err } @@ -223,10 +224,10 @@ func (list *List) GetEntityType() (string, error) { } // ReserveListItemID reserves item's ID in this list -func (list *List) ReserveListItemID() (int, error) { +func (list *List) ReserveListItemID(ctx context.Context) (int, error) { client := NewHTTPClient(list.client) endpoint := fmt.Sprintf("%s/ReserveListItemId", list.endpoint) - data, err := client.Post(endpoint, nil, list.config) + data, err := client.Post(ctx, endpoint, nil, list.config) if err != nil { return 0, err } @@ -244,13 +245,13 @@ func (list *List) ReserveListItemID() (int, error) { } // RenderListData renders lists content using CAML -func (list *List) RenderListData(viewXML string) (RenderListDataResp, error) { +func (list *List) RenderListData(ctx context.Context, viewXML string) (RenderListDataResp, error) { client := NewHTTPClient(list.client) apiURL, _ := url.Parse(fmt.Sprintf("%s/RenderListData(@viewXml)", list.endpoint)) query := apiURL.Query() query.Set("@viewXml", `'`+TrimMultiline(viewXML)+`'`) apiURL.RawQuery = query.Encode() - data, err := client.Post(apiURL.String(), nil, list.config) + data, err := client.Post(ctx, apiURL.String(), nil, list.config) if err != nil { return nil, err } @@ -280,8 +281,8 @@ func (list *List) Roles() *Roles { } // ContextInfo gets context info for a web of current list -func (list *List) ContextInfo() (*ContextInfo, error) { - return NewContext(list.client, list.ToURL(), list.config).Get() +func (list *List) ContextInfo(ctx context.Context) (*ContextInfo, error) { + return NewContext(list.client, list.ToURL(), list.config).Get(ctx) } /* Response helpers */ diff --git a/api/list_test.go b/api/list_test.go index 9cee067..8f1814d 100644 --- a/api/list_test.go +++ b/api/list_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "strings" "testing" @@ -13,15 +14,15 @@ func TestList(t *testing.T) { web := NewSP(spClient).Web() listTitle := strings.Replace(uuid.New().String(), "-", "", -1) - listInfo, err := web.Lists().Add(listTitle, nil) + listInfo, err := web.Lists().Add(context.Background(), listTitle, nil) if err != nil { t.Error(err) } list := web.Lists().GetByID(listInfo.Data().ID) - defer func() { _ = list.Delete() }() + defer func() { _ = list.Delete(context.Background()) }() t.Run("GetEntityType", func(t *testing.T) { - entType, err := list.GetEntityType() + entType, err := list.GetEntityType(context.Background()) if err != nil { t.Error(err) } @@ -31,7 +32,7 @@ func TestList(t *testing.T) { }) t.Run("Get", func(t *testing.T) { - l, err := list.Get() // .Select("*") + l, err := list.Get(context.Background()) // .Select("*") if err != nil { t.Error(err) } @@ -44,19 +45,19 @@ func TestList(t *testing.T) { }) t.Run("Items", func(t *testing.T) { - if _, err := list.Items().Select("Id").Top(1).Get(); err != nil { + if _, err := list.Items().Select("Id").Top(1).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("ParentWeb", func(t *testing.T) { - if _, err := list.ParentWeb().Get(); err != nil { + if _, err := list.ParentWeb().Get(context.Background()); err != nil { t.Error(err) } }) t.Run("ReserveListItemID", func(t *testing.T) { - nextID, err := list.ReserveListItemID() + nextID, err := list.ReserveListItemID(context.Background()) if err != nil { t.Error(err) } @@ -66,7 +67,7 @@ func TestList(t *testing.T) { }) t.Run("RenderListData", func(t *testing.T) { - listData, err := list.RenderListData(``) + listData, err := list.RenderListData(context.Background(), ``) if err != nil { t.Error(err) } @@ -76,18 +77,18 @@ func TestList(t *testing.T) { }) t.Run("RootFolder", func(t *testing.T) { - if _, err := list.RootFolder().Get(); err != nil { + if _, err := list.RootFolder().Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Recycle", func(t *testing.T) { guid := uuid.New().String() - lr, err := web.Lists().Add(guid, nil) + lr, err := web.Lists().Add(context.Background(), guid, nil) if err != nil { t.Error(err) } - if err := web.Lists().GetByID(lr.Data().ID).Recycle(); err != nil { + if err := web.Lists().GetByID(lr.Data().ID).Recycle(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/lists.go b/api/lists.go index b1de364..f3d63da 100644 --- a/api/lists.go +++ b/api/lists.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -38,9 +39,9 @@ func (lists *Lists) ToURL() string { } // Get gets Lists API queryable collection -func (lists *Lists) Get() (ListsResp, error) { +func (lists *Lists) Get(ctx context.Context) (ListsResp, error) { client := NewHTTPClient(lists.client) - return client.Get(lists.ToURL(), lists.config) + return client.Get(ctx, lists.ToURL(), lists.config) } // GetByTitle gets a list by its Display Name (Title) @@ -66,7 +67,7 @@ func (lists *Lists) GetByID(listGUID string) *List { // Add creates new list on this web with a provided `title`. // Along with title additional metadata can be provided in optional `metadata` string map object. // `metadata` props should correspond to `SP.List` API type. Some props have defaults as BaseTemplate (100), AllowContentTypes (false), etc. -func (lists *Lists) Add(title string, metadata map[string]interface{}) (ListResp, error) { +func (lists *Lists) Add(ctx context.Context, title string, metadata map[string]interface{}) (ListResp, error) { if metadata == nil { metadata = make(map[string]interface{}) } @@ -95,15 +96,19 @@ func (lists *Lists) Add(title string, metadata map[string]interface{}) (ListResp headers["Accept"] = "application/json;odata=verbose" headers["Content-Type"] = "application/json;odata=verbose;charset=utf-8" - return client.Post(lists.endpoint, bytes.NewBuffer([]byte(body)), patchConfigHeaders(lists.config, headers)) + return client.Post( + ctx, + lists.endpoint, + bytes.NewBuffer([]byte(body)), + patchConfigHeaders(lists.config, headers)) } // AddWithURI creates new list on this web with a provided `title` and `uri`. // `url` stands for a system friendly URI (e.g. `custom-list`) while `title` is a human friendly name (e.g. `Custom List`). // Along with uri and title additional metadata can be provided in optional `metadata` string map object. // `metadata` props should correspond to `SP.List` API type. Some props have defaults as BaseTemplate (100), AllowContentTypes (false), etc. -func (lists *Lists) AddWithURI(title string, uri string, metadata map[string]interface{}) ([]byte, error) { - data, err := lists.Conf(HeadersPresets.Verbose).Add(uri, metadata) +func (lists *Lists) AddWithURI(ctx context.Context, title string, uri string, metadata map[string]interface{}) ([]byte, error) { + data, err := lists.Conf(HeadersPresets.Verbose).Add(ctx, uri, metadata) if err != nil { return nil, err } @@ -113,5 +118,5 @@ func (lists *Lists) AddWithURI(title string, uri string, metadata map[string]int metadata["Title"] = title body, _ := json.Marshal(metadata) - return lists.GetByID(data.Data().ID).Update(body) + return lists.GetByID(data.Data().ID).Update(ctx, body) } diff --git a/api/lists_test.go b/api/lists_test.go index 941e4da..0d70a66 100644 --- a/api/lists_test.go +++ b/api/lists_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "strings" "testing" @@ -16,7 +17,7 @@ func TestLists(t *testing.T) { newListTitle := uuid.New().String() t.Run("Get", func(t *testing.T) { - data, err := web.Lists().Select("Id,Title").Conf(headers.verbose).Get() + data, err := web.Lists().Select("Id,Title").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -29,7 +30,7 @@ func TestLists(t *testing.T) { }) t.Run("Add", func(t *testing.T) { - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } }) @@ -39,7 +40,7 @@ func TestLists(t *testing.T) { if err != nil { t.Error(err) } - if _, err := web.Lists().GetByID(listInfo.ID).Get(); err != nil { + if _, err := web.Lists().GetByID(listInfo.ID).Get(context.Background()); err != nil { t.Error(err) } }) @@ -49,7 +50,7 @@ func TestLists(t *testing.T) { if err != nil { t.Error(err) } - if _, err := web.Lists().GetByTitle(listInfo.Title).Get(); err != nil { + if _, err := web.Lists().GetByTitle(listInfo.Title).Get(context.Background()); err != nil { t.Error(err) } }) @@ -57,7 +58,7 @@ func TestLists(t *testing.T) { t.Run("GetListByURI", func(t *testing.T) { listURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Lists/" + strings.Replace(newListTitle, "-", "", -1) - if _, err := web.GetList(listURI).Get(); err != nil { + if _, err := web.GetList(listURI).Get(context.Background()); err != nil { t.Error(err) } }) @@ -69,10 +70,10 @@ func TestLists(t *testing.T) { listTitle := uuid.New().String() listURI := uuid.New().String() - if _, err := web.Lists().AddWithURI(listTitle, listURI, nil); err != nil { + if _, err := web.Lists().AddWithURI(context.Background(), listTitle, listURI, nil); err != nil { t.Error(err) } - if err := web.Lists().GetByTitle(listTitle).Delete(); err != nil { + if err := web.Lists().GetByTitle(listTitle).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -80,16 +81,16 @@ func TestLists(t *testing.T) { t.Run("CreateFieldAsXML", func(t *testing.T) { title := strings.Replace(uuid.New().String(), "-", "", -1) schemaXML := `` - if _, err := web.Lists().GetByTitle(newListTitle).Fields().CreateFieldAsXML(schemaXML, 12); err != nil { + if _, err := web.Lists().GetByTitle(newListTitle).Fields().CreateFieldAsXML(context.Background(), schemaXML, 12); err != nil { t.Error(err) } - if err := web.Lists().GetByTitle(newListTitle).Fields().GetByInternalNameOrTitle(title).Delete(); err != nil { + if err := web.Lists().GetByTitle(newListTitle).Fields().GetByInternalNameOrTitle(title).Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("Delete", func(t *testing.T) { - if err := web.Lists().GetByTitle(newListTitle).Delete(); err != nil { + if err := web.Lists().GetByTitle(newListTitle).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -98,7 +99,7 @@ func TestLists(t *testing.T) { func getAnyList() (*ListInfo, error) { web := NewSP(spClient).Web() - data, err := web.Lists().Select("Id,Title").OrderBy("Created", true).Top(1).Conf(headers.verbose).Get() + data, err := web.Lists().Select("Id,Title").OrderBy("Created", true).Top(1).Conf(headers.verbose).Get(context.Background()) if err != nil { return nil, err } diff --git a/api/mmd.go b/api/mmd.go index c30f0e1..c27f18f 100644 --- a/api/mmd.go +++ b/api/mmd.go @@ -7,6 +7,8 @@ import ( "strconv" "strings" + "context" + "github.com/koltyakov/gosip" "github.com/koltyakov/gosip/csom" ) @@ -61,13 +63,13 @@ func trimTaxonomyGUID(guid string) string { return guid } -func csomResponse(httpClient *HTTPClient, siteURL string, config *RequestConfig, csomBuilder csom.Builder) (map[string]interface{}, error) { +func csomResponse(ctx context.Context, httpClient *HTTPClient, siteURL string, config *RequestConfig, csomBuilder csom.Builder) (map[string]interface{}, error) { csomPkg, err := csomBuilder.Compile() if err != nil { return nil, err } - jsomResp, err := httpClient.ProcessQuery(siteURL, bytes.NewBuffer([]byte(csomPkg)), config) + jsomResp, err := httpClient.ProcessQuery(ctx, siteURL, bytes.NewBuffer([]byte(csomPkg)), config) if err != nil { // Retry Terms update conflicts if strings.Contains(err.Error(), "Term update failed because of save conflict") { @@ -84,7 +86,7 @@ func csomResponse(httpClient *HTTPClient, siteURL string, config *RequestConfig, retry, _ := strconv.Atoi(retryStr) config.Headers["X-Gosip-Retry"] = strconv.Itoa(retry + 1) if retry+1 <= 5 { - return csomResponse(httpClient, siteURL, config, csomBuilder) + return csomResponse(ctx, httpClient, siteURL, config, csomBuilder) } } return nil, err @@ -107,8 +109,8 @@ func csomResponse(httpClient *HTTPClient, siteURL string, config *RequestConfig, return res, nil } -func csomRespChildItems(httpClient *HTTPClient, siteURL string, config *RequestConfig, csomBuilder csom.Builder) ([]map[string]interface{}, error) { - data, err := csomResponse(httpClient, siteURL, config, csomBuilder) +func csomRespChildItems(ctx context.Context, httpClient *HTTPClient, siteURL string, config *RequestConfig, csomBuilder csom.Builder) ([]map[string]interface{}, error) { + data, err := csomResponse(ctx, httpClient, siteURL, config, csomBuilder) if err != nil { return nil, err } @@ -130,8 +132,8 @@ func csomRespChildItems(httpClient *HTTPClient, siteURL string, config *RequestC return resItems, nil } -func csomRespChildItemsInProp(httpClient *HTTPClient, siteURL string, config *RequestConfig, csomBuilder csom.Builder, prop string) ([]map[string]interface{}, error) { - data, err := csomResponse(httpClient, siteURL, config, csomBuilder) +func csomRespChildItemsInProp(ctx context.Context, httpClient *HTTPClient, siteURL string, config *RequestConfig, csomBuilder csom.Builder, prop string) ([]map[string]interface{}, error) { + data, err := csomResponse(ctx, httpClient, siteURL, config, csomBuilder) if err != nil { return nil, err } diff --git a/api/mmd_groups.go b/api/mmd_groups.go index 59c1bc8..f19eba3 100644 --- a/api/mmd_groups.go +++ b/api/mmd_groups.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "strings" @@ -17,13 +18,13 @@ type TermGroups struct { } // Get gets term groups metadata -func (termGroups *TermGroups) Get() ([]map[string]interface{}, error) { +func (termGroups *TermGroups) Get(ctx context.Context) ([]map[string]interface{}, error) { b := termGroups.csomEntry.Clone() b.AddAction(csom.NewQueryWithProps([]string{ ``, }), nil) - return csomRespChildItemsInProp(termGroups.client, termGroups.endpoint, termGroups.config, b, "Groups") + return csomRespChildItemsInProp(ctx, termGroups.client, termGroups.endpoint, termGroups.config, b, "Groups") } // GetByID gets term group object by its GUID @@ -40,14 +41,14 @@ func (termGroups *TermGroups) GetByID(groupGUID string) *TermGroup { } // Add creates new group -func (termGroups *TermGroups) Add(name string, guid string) (map[string]interface{}, error) { +func (termGroups *TermGroups) Add(ctx context.Context, name string, guid string) (map[string]interface{}, error) { b := termGroups.csomEntry.Clone() b.AddObject(csom.NewObjectMethod("CreateGroup", []string{ fmt.Sprintf(`%s`, name), fmt.Sprintf(`%s`, guid), }), nil) b.AddAction(csom.NewQueryWithProps([]string{}), nil) - return csomResponse(termGroups.client, termGroups.endpoint, termGroups.config, b) + return csomResponse(ctx, termGroups.client, termGroups.endpoint, termGroups.config, b) } /* Term Group */ @@ -81,7 +82,7 @@ func (termGroup *TermGroup) Select(props string) *TermGroup { } // Get gets term group metadata -func (termGroup *TermGroup) Get() (map[string]interface{}, error) { +func (termGroup *TermGroup) Get(ctx context.Context) (map[string]interface{}, error) { var props []string for _, prop := range termGroup.selectProps { propertyXML := prop @@ -94,14 +95,14 @@ func (termGroup *TermGroup) Get() (map[string]interface{}, error) { b := termGroup.csomBuilderEntry() b.AddAction(csom.NewQueryWithProps(props), nil) - return csomResponse(termGroup.client, termGroup.endpoint, termGroup.config, b) + return csomResponse(ctx, termGroup.client, termGroup.endpoint, termGroup.config, b) } // Delete deletes group object -func (termGroup *TermGroup) Delete() error { +func (termGroup *TermGroup) Delete(ctx context.Context) error { b := termGroup.csomBuilderEntry().Clone() b.AddAction(csom.NewActionMethod("DeleteObject", []string{}), nil) - _, err := csomResponse(termGroup.client, termGroup.endpoint, termGroup.config, b) + _, err := csomResponse(ctx, termGroup.client, termGroup.endpoint, termGroup.config, b) return err } diff --git a/api/mmd_sets.go b/api/mmd_sets.go index e901d94..7805f48 100644 --- a/api/mmd_sets.go +++ b/api/mmd_sets.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "strings" @@ -23,13 +24,13 @@ func (termSets *TermSets) csomBuilderEntry() csom.Builder { } // Get gets term sets metadata -func (termSets *TermSets) Get() ([]map[string]interface{}, error) { +func (termSets *TermSets) Get(ctx context.Context) ([]map[string]interface{}, error) { b := termSets.csomBuilderEntry().Clone() b.AddAction(csom.NewQueryWithProps([]string{ ``, }), nil) - return csomRespChildItemsInProp(termSets.client, termSets.endpoint, termSets.config, b, "TermSets") + return csomRespChildItemsInProp(ctx, termSets.client, termSets.endpoint, termSets.config, b, "TermSets") } // GetByID gets term set object by its GUID @@ -47,7 +48,7 @@ func (termSets *TermSets) GetByID(setGUID string) *TermSet { } // GetByName gets term sets by a name and LCID, searches within term store -func (termSets *TermSets) GetByName(termSetName string, lcid int) ([]map[string]interface{}, error) { +func (termSets *TermSets) GetByName(ctx context.Context, termSetName string, lcid int) ([]map[string]interface{}, error) { b := csom.NewBuilder() objs := termSets.csomBuilderEntry().GetObjects() @@ -62,11 +63,11 @@ func (termSets *TermSets) GetByName(termSetName string, lcid int) ([]map[string] fmt.Sprintf(`%d`, lcid), }), nil) b.AddAction(csom.NewQueryWithChildProps([]string{}), nil) - return csomRespChildItems(termSets.client, termSets.endpoint, termSets.config, b) + return csomRespChildItems(ctx, termSets.client, termSets.endpoint, termSets.config, b) } // Add creates new term set -func (termSets *TermSets) Add(name string, guid string, lcid int) (map[string]interface{}, error) { +func (termSets *TermSets) Add(ctx context.Context, name string, guid string, lcid int) (map[string]interface{}, error) { b := termSets.csomBuilderEntry().Clone() b.AddObject(csom.NewObjectMethod("CreateTermSet", []string{ fmt.Sprintf(`%s`, name), @@ -74,7 +75,7 @@ func (termSets *TermSets) Add(name string, guid string, lcid int) (map[string]in fmt.Sprintf(`%d`, lcid), }), nil) b.AddAction(csom.NewQueryWithProps([]string{}), nil) - return csomResponse(termSets.client, termSets.endpoint, termSets.config, b) + return csomResponse(ctx, termSets.client, termSets.endpoint, termSets.config, b) } /* Term Sets */ @@ -107,7 +108,7 @@ func (termSet *TermSet) Select(props string) *TermSet { } // Get gets term set metadata -func (termSet *TermSet) Get() (map[string]interface{}, error) { +func (termSet *TermSet) Get(ctx context.Context) (map[string]interface{}, error) { var props []string for _, prop := range termSet.selectProps { propertyXML := prop @@ -120,14 +121,14 @@ func (termSet *TermSet) Get() (map[string]interface{}, error) { b := termSet.csomBuilderEntry().Clone() b.AddAction(csom.NewQueryWithProps(props), nil) - return csomResponse(termSet.client, termSet.endpoint, termSet.config, b) + return csomResponse(ctx, termSet.client, termSet.endpoint, termSet.config, b) } // Delete deletes term set object -func (termSet *TermSet) Delete() error { +func (termSet *TermSet) Delete(ctx context.Context) error { b := termSet.csomBuilderEntry().Clone() b.AddAction(csom.NewActionMethod("DeleteObject", []string{}), nil) - _, err := csomResponse(termSet.client, termSet.endpoint, termSet.config, b) + _, err := csomResponse(ctx, termSet.client, termSet.endpoint, termSet.config, b) return err } @@ -144,7 +145,7 @@ func (termSet *TermSet) Terms() *Terms { } // GetAllTerms gets all terms collection metadata -func (termSet *TermSet) GetAllTerms() ([]map[string]interface{}, error) { +func (termSet *TermSet) GetAllTerms(ctx context.Context) ([]map[string]interface{}, error) { var props []string for _, prop := range termSet.selectProps { propertyXML := prop @@ -158,5 +159,5 @@ func (termSet *TermSet) GetAllTerms() ([]map[string]interface{}, error) { b.AddObject(csom.NewObjectMethod("GetAllTerms", []string{}), nil) b.AddAction(csom.NewQueryWithChildProps(props), nil) - return csomRespChildItems(termSet.client, termSet.endpoint, termSet.config, b) + return csomRespChildItems(ctx, termSet.client, termSet.endpoint, termSet.config, b) } diff --git a/api/mmd_stores.go b/api/mmd_stores.go index 379dacf..b8a8cd2 100644 --- a/api/mmd_stores.go +++ b/api/mmd_stores.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "strings" @@ -100,7 +101,7 @@ func (termStore *TermStore) Select(props string) *TermStore { } // Get gets term store metadata -func (termStore *TermStore) Get() (map[string]interface{}, error) { +func (termStore *TermStore) Get(ctx context.Context) (map[string]interface{}, error) { var props []string for _, prop := range termStore.selectProps { propertyXML := prop @@ -113,7 +114,7 @@ func (termStore *TermStore) Get() (map[string]interface{}, error) { b := termStore.csomBuilderEntry() b.AddAction(csom.NewQueryWithProps(props), nil) - return csomResponse(termStore.client, termStore.endpoint, termStore.config, b) + return csomResponse(ctx, termStore.client, termStore.endpoint, termStore.config, b) } // // CommitAll commits all changes @@ -125,10 +126,10 @@ func (termStore *TermStore) Get() (map[string]interface{}, error) { // } // UpdateCache updates store cache -func (termStore *TermStore) UpdateCache() error { +func (termStore *TermStore) UpdateCache(ctx context.Context) error { b := termStore.csomBuilderEntry().Clone() b.AddAction(csom.NewActionMethod("UpdateCache", []string{}), nil) - _, err := csomResponse(termStore.client, termStore.endpoint, termStore.config, b) + _, err := csomResponse(ctx, termStore.client, termStore.endpoint, termStore.config, b) return err } diff --git a/api/mmd_terms.go b/api/mmd_terms.go index d4355c4..c7f3fd3 100644 --- a/api/mmd_terms.go +++ b/api/mmd_terms.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "strings" @@ -30,13 +31,13 @@ func (terms *Terms) Select(props string) *Terms { } // Get gets child terms -func (terms *Terms) Get() ([]map[string]interface{}, error) { +func (terms *Terms) Get(ctx context.Context) ([]map[string]interface{}, error) { b := terms.csomEntry.Clone() b.AddAction(csom.NewQueryWithProps([]string{ ``, }), nil) - return csomRespChildItemsInProp(terms.client, terms.endpoint, terms.config, b, "Terms") + return csomRespChildItemsInProp(ctx, terms.client, terms.endpoint, terms.config, b, "Terms") } // GetByID gets a term by its GUID @@ -52,7 +53,7 @@ func (terms *Terms) GetByID(termGUID string) *Term { } // Add creates new term -func (terms *Terms) Add(name string, guid string, lcid int) (map[string]interface{}, error) { +func (terms *Terms) Add(ctx context.Context, name string, guid string, lcid int) (map[string]interface{}, error) { b := terms.csomBuilderEntry().Clone() b.AddObject(csom.NewObjectMethod("CreateTerm", []string{ fmt.Sprintf(`%s`, name), @@ -60,7 +61,7 @@ func (terms *Terms) Add(name string, guid string, lcid int) (map[string]interfac fmt.Sprintf(`%s`, guid), }), nil) b.AddAction(csom.NewQueryWithProps([]string{}), nil) - return csomResponse(terms.client, terms.endpoint, terms.config, b) + return csomResponse(ctx, terms.client, terms.endpoint, terms.config, b) } /* Term */ @@ -94,7 +95,7 @@ func (term *Term) Select(props string) *Term { } // Get gets term metadata -func (term *Term) Get() (map[string]interface{}, error) { +func (term *Term) Get(ctx context.Context) (map[string]interface{}, error) { var props []string for _, prop := range term.selectProps { propertyXML := prop @@ -107,11 +108,11 @@ func (term *Term) Get() (map[string]interface{}, error) { b := term.csomBuilderEntry().Clone() b.AddAction(csom.NewQueryWithProps(props), nil) - return csomResponse(term.client, term.endpoint, term.config, b) + return csomResponse(ctx, term.client, term.endpoint, term.config, b) } // Update sets term's properties -func (term *Term) Update(properties map[string]interface{}) (map[string]interface{}, error) { +func (term *Term) Update(ctx context.Context, properties map[string]interface{}) (map[string]interface{}, error) { b := term.csomBuilderEntry().Clone() objects := b.GetObjects() // get parent from all objects termObject := objects[len(objects)-1] @@ -125,30 +126,30 @@ func (term *Term) Update(properties map[string]interface{}) (map[string]interfac // scalarProperties = append(scalarProperties, fmt.Sprintf(``, prop)) } b.AddAction(csom.NewQueryWithProps([]string{}), termObject) // scalarProperties - return csomResponse(term.client, term.endpoint, term.config, b) + return csomResponse(ctx, term.client, term.endpoint, term.config, b) } // Delete deletes term object -func (term *Term) Delete() error { +func (term *Term) Delete(ctx context.Context) error { b := term.csomBuilderEntry().Clone() b.AddAction(csom.NewActionMethod("DeleteObject", []string{}), nil) - _, err := csomResponse(term.client, term.endpoint, term.config, b) + _, err := csomResponse(ctx, term.client, term.endpoint, term.config, b) return err } // Deprecate deprecates/activates a term -func (term *Term) Deprecate(deprecate bool) error { +func (term *Term) Deprecate(ctx context.Context, deprecate bool) error { b := term.csomBuilderEntry().Clone() b.AddAction(csom.NewActionMethod("Deprecate", []string{ fmt.Sprintf(`%t`, deprecate), }), nil) - _, err := csomResponse(term.client, term.endpoint, term.config, b) + _, err := csomResponse(ctx, term.client, term.endpoint, term.config, b) return err } // Move moves a term to a new location // use empty `termGUID` to move to a root term store level -func (term *Term) Move(termSetGUID string, termGUID string) error { +func (term *Term) Move(ctx context.Context, termSetGUID string, termGUID string) error { termSetGUID = trimTaxonomyGUID(termSetGUID) termGUID = trimTaxonomyGUID(termGUID) @@ -174,7 +175,7 @@ func (term *Term) Move(termSetGUID string, termGUID string) error { fmt.Sprintf(``, parentObj.GetID()), }), childTermObj) - _, err := csomResponse(term.client, term.endpoint, term.config, b) + _, err := csomResponse(ctx, term.client, term.endpoint, term.config, b) return err } diff --git a/api/mmd_test.go b/api/mmd_test.go index c6eae45..3639c88 100644 --- a/api/mmd_test.go +++ b/api/mmd_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "strings" "testing" @@ -14,7 +15,7 @@ func TestTaxonomyStores(t *testing.T) { taxonomy := NewSP(spClient).Taxonomy() t.Run("Default", func(t *testing.T) { - tsInfo, err := taxonomy.Stores().Default().Get() + tsInfo, err := taxonomy.Stores().Default().Get(context.Background()) if err != nil { t.Errorf("can't get term store info, %s\n", err) } @@ -24,11 +25,11 @@ func TestTaxonomyStores(t *testing.T) { }) t.Run("GetByID", func(t *testing.T) { - tsInfo, err := taxonomy.Stores().Default().Get() + tsInfo, err := taxonomy.Stores().Default().Get(context.Background()) if err != nil { t.Errorf("can't get term store info, %s\n", err) } - data, err := taxonomy.Stores().GetByID(tsInfo["Id"].(string)).Get() + data, err := taxonomy.Stores().GetByID(tsInfo["Id"].(string)).Get(context.Background()) if err != nil { t.Errorf("can't get term store info, %s\n", err) } @@ -38,11 +39,11 @@ func TestTaxonomyStores(t *testing.T) { }) t.Run("GetByName", func(t *testing.T) { - tsInfo, err := taxonomy.Stores().Default().Get() + tsInfo, err := taxonomy.Stores().Default().Get(context.Background()) if err != nil { t.Errorf("can't get term store info, %s\n", err) } - data, err := taxonomy.Stores().GetByName(tsInfo["Name"].(string)).Get() + data, err := taxonomy.Stores().GetByName(tsInfo["Name"].(string)).Get(context.Background()) if err != nil { t.Errorf("can't get term store info, %s\n", err) } @@ -64,7 +65,7 @@ func TestTaxonomyStores(t *testing.T) { if len(ts.selectProps) != 4 { t.Error("error setting props") } - data, err := ts.Get() + data, err := ts.Get(context.Background()) if err != nil { t.Errorf("can't get term store info, %s\n", err) } @@ -77,13 +78,13 @@ func TestTaxonomyStores(t *testing.T) { }) t.Run("UpdateCache", func(t *testing.T) { - if err := taxonomy.Stores().Default().UpdateCache(); err != nil { + if err := taxonomy.Stores().Default().UpdateCache(context.Background()); err != nil { t.Errorf("can't get term store info, %s\n", err) } }) t.Run("Sets/GetByName", func(t *testing.T) { - sets, err := taxonomy.Stores().Default().Sets().GetByName("Department", 1033) + sets, err := taxonomy.Stores().Default().Sets().GetByName(context.Background(), "Department", 1033) if err != nil { t.Errorf("can't get term set by name, %s\n", err) } @@ -102,7 +103,7 @@ func TestTaxonomyGroups(t *testing.T) { newGroupName := "Delete me " + newGroupGUID t.Run("Get", func(t *testing.T) { - gs, err := taxonomy.Stores().Default().Groups().Get() + gs, err := taxonomy.Stores().Default().Groups().Get(context.Background()) if err != nil { t.Error(err) } @@ -120,7 +121,7 @@ func TestTaxonomyGroups(t *testing.T) { t.Error(err) } - group, err := taxonomy.Stores().Default().Groups().GetByID(groupGUID).Select("Id,Name").Get() + group, err := taxonomy.Stores().Default().Groups().GetByID(groupGUID).Select("Id,Name").Get(context.Background()) if err != nil { t.Error(err) } @@ -131,7 +132,7 @@ func TestTaxonomyGroups(t *testing.T) { }) t.Run("Add", func(t *testing.T) { - group, err := taxonomy.Stores().Default().Groups().Add(newGroupName, newGroupGUID) + group, err := taxonomy.Stores().Default().Groups().Add(context.Background(), newGroupName, newGroupGUID) if err != nil { t.Error(err) } @@ -141,13 +142,13 @@ func TestTaxonomyGroups(t *testing.T) { }) t.Run("Delete", func(t *testing.T) { - if err := taxonomy.Stores().Default().Groups().GetByID(newGroupGUID).Delete(); err != nil { + if err := taxonomy.Stores().Default().Groups().GetByID(newGroupGUID).Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("Sets/GetByName", func(t *testing.T) { - sets, err := taxonomy.Stores().Default().Groups().GetByID("any-id-should-work-here").Sets().GetByName("Department", 1033) + sets, err := taxonomy.Stores().Default().Groups().GetByID("any-id-should-work-here").Sets().GetByName(context.Background(), "Department", 1033) if err != nil { t.Errorf("can't get term set by name, %s\n", err) } @@ -176,7 +177,7 @@ func TestTaxonomyTermSets(t *testing.T) { newTermSetName := "Delete me " + newTermSetGUID t.Run("GetByID", func(t *testing.T) { - data, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Select("Id").Get() + data, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Select("Id").Get(context.Background()) if err != nil { t.Errorf("can't get term set by ID, %s\n", err) } @@ -186,14 +187,14 @@ func TestTaxonomyTermSets(t *testing.T) { }) t.Run("GetAllTerms", func(t *testing.T) { - _, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Select("Id,Name").GetAllTerms() + _, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Select("Id,Name").GetAllTerms(context.Background()) if err != nil { t.Errorf("%s", err) } }) t.Run("Terms/Get", func(t *testing.T) { - _, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Terms().Select("Id,Name").Get() + _, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Terms().Select("Id,Name").Get(context.Background()) if err != nil { t.Errorf("%s", err) } @@ -202,13 +203,13 @@ func TestTaxonomyTermSets(t *testing.T) { t.Run("Add", func(t *testing.T) { store := taxonomy.Stores().Default() - tsInfo, err := store.Select("DefaultLanguage").Get() + tsInfo, err := store.Select("DefaultLanguage").Get(context.Background()) if err != nil { t.Error(err) } lang := int(tsInfo["DefaultLanguage"].(float64)) - termSet, err := store.Groups().GetByID(termGroupID).Sets().Add(newTermSetName, newTermSetGUID, lang) + termSet, err := store.Groups().GetByID(termGroupID).Sets().Add(context.Background(), newTermSetName, newTermSetGUID, lang) if err != nil { t.Error(err) } @@ -219,7 +220,7 @@ func TestTaxonomyTermSets(t *testing.T) { t.Run("Delete", func(t *testing.T) { store := taxonomy.Stores().Default() - if err := store.Sets().GetByID(newTermSetGUID).Delete(); err != nil { + if err := store.Sets().GetByID(newTermSetGUID).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -241,7 +242,7 @@ func TestTaxonomyTerms(t *testing.T) { } t.Run("Store/GetTerm", func(t *testing.T) { - termInfo, err := taxonomy.Stores().Default().Terms().GetByID(termGUID).Select("Id").Get() + termInfo, err := taxonomy.Stores().Default().Terms().GetByID(termGUID).Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -252,7 +253,7 @@ func TestTaxonomyTerms(t *testing.T) { t.Run("TermSet/GetByID", func(t *testing.T) { termSet := taxonomy.Stores().Default().Sets().GetByID(termSetGUID) - termInfo, err := termSet.Terms().GetByID(termGUID).Select("Id").Get() + termInfo, err := termSet.Terms().GetByID(termGUID).Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -262,7 +263,7 @@ func TestTaxonomyTerms(t *testing.T) { }) t.Run("Terms/CRUD", func(t *testing.T) { - tsInfo, err := taxonomy.Stores().Default().Select("DefaultLanguage").Get() + tsInfo, err := taxonomy.Stores().Default().Select("DefaultLanguage").Get(context.Background()) if err != nil { t.Error(err) } @@ -273,7 +274,7 @@ func TestTaxonomyTerms(t *testing.T) { t.Run("Add", func(t *testing.T) { termSet := taxonomy.Stores().Default().Sets().GetByID(termSetGUID) - termInfo, err := termSet.Terms().Add(newTermName, newTermGUID, lang) + termInfo, err := termSet.Terms().Add(context.Background(), newTermName, newTermGUID, lang) if err != nil { t.Error(err) } @@ -289,7 +290,7 @@ func TestTaxonomyTerms(t *testing.T) { store := taxonomy.Stores().Default() parentTerm := store.Terms().GetByID(newTermGUID) - termInfo, err := parentTerm.Terms().Add(subTermName, subTermGUID, lang) + termInfo, err := parentTerm.Terms().Add(context.Background(), subTermName, subTermGUID, lang) if err != nil { t.Error(err) } @@ -297,7 +298,7 @@ func TestTaxonomyTerms(t *testing.T) { t.Error("unexpected term ID") } - subTerms, err := parentTerm.Terms().Get() + subTerms, err := parentTerm.Terms().Get(context.Background()) if err != nil { t.Error(err) } @@ -312,12 +313,12 @@ func TestTaxonomyTerms(t *testing.T) { termSet := taxonomy.Stores().Default().Sets().GetByID(termSetGUID) - if _, err := termSet.Terms().Add(childTermName, childTermGUID, lang); err != nil { + if _, err := termSet.Terms().Add(context.Background(), childTermName, childTermGUID, lang); err != nil { t.Error(err) } childTerm := termSet.Terms().GetByID(childTermGUID) - if err := childTerm.Move(termSetGUID, newTermGUID); err != nil { + if err := childTerm.Move(context.Background(), termSetGUID, newTermGUID); err != nil { t.Error(err) } }) @@ -328,30 +329,30 @@ func TestTaxonomyTerms(t *testing.T) { termSet := taxonomy.Stores().Default().Sets().GetByID(termSetGUID) - if _, err := termSet.Terms().GetByID(newTermGUID).Terms().Add(childTermName, childTermGUID, lang); err != nil { + if _, err := termSet.Terms().GetByID(newTermGUID).Terms().Add(context.Background(), childTermName, childTermGUID, lang); err != nil { t.Error(err) } childTerm := termSet.Terms().GetByID(childTermGUID) - if err := childTerm.Move(termSetGUID, ""); err != nil { + if err := childTerm.Move(context.Background(), termSetGUID, ""); err != nil { t.Error(err) } - if err := childTerm.Delete(); err != nil { + if err := childTerm.Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("Add#FailAddingADuplicate", func(t *testing.T) { termSet := taxonomy.Stores().Default().Sets().GetByID(termSetGUID) - if _, err := termSet.Terms().Add(newTermName, newTermGUID, lang); err == nil { + if _, err := termSet.Terms().Add(context.Background(), newTermName, newTermGUID, lang); err == nil { t.Error("should fail with duplicate error message") } }) t.Run("Get", func(t *testing.T) { term := taxonomy.Stores().Default().Terms().GetByID(newTermGUID) - if _, err := term.Get(); err != nil { + if _, err := term.Get(context.Background()); err != nil { t.Error(err) } }) @@ -360,7 +361,7 @@ func TestTaxonomyTerms(t *testing.T) { updateTermName := newTermName + " (updated)" props := map[string]interface{}{"Name": updateTermName} term := taxonomy.Stores().Default().Terms().GetByID(newTermGUID) - termAfterUpdate, err := term.Update(props) + termAfterUpdate, err := term.Update(context.Background(), props) if err != nil { t.Error(err) } @@ -372,7 +373,7 @@ func TestTaxonomyTerms(t *testing.T) { t.Run("Deprecate", func(t *testing.T) { store := taxonomy.Stores().Default() term := store.Terms().GetByID(newTermGUID) - if err := term.Deprecate(true); err != nil { + if err := term.Deprecate(context.Background(), true); err != nil { t.Error(err) } // if err := store.UpdateCache(); err != nil { @@ -391,7 +392,7 @@ func TestTaxonomyTerms(t *testing.T) { t.Run("Activate", func(t *testing.T) { store := taxonomy.Stores().Default() term := store.Terms().GetByID(newTermGUID) - if err := term.Deprecate(false); err != nil { + if err := term.Deprecate(context.Background(), false); err != nil { t.Error(err) } // if err := store.UpdateCache(); err != nil { @@ -409,7 +410,7 @@ func TestTaxonomyTerms(t *testing.T) { t.Run("Delete", func(t *testing.T) { term := taxonomy.Stores().Default().Terms().GetByID(newTermGUID) - if err := term.Delete(); err != nil { + if err := term.Delete(context.Background()); err != nil { t.Error(err) } }) @@ -423,7 +424,7 @@ func TestTaxonomyNotFoundIDs(t *testing.T) { store := taxonomy.Stores().Default() t.Run("Groups/GetByID", func(t *testing.T) { - _, err := store.Groups().GetByID("wrong-id").Get() + _, err := store.Groups().GetByID("wrong-id").Get(context.Background()) if err == nil { t.Error("should fail with Guid should contain 32 digits with 4 dashes message") } @@ -431,7 +432,7 @@ func TestTaxonomyNotFoundIDs(t *testing.T) { t.Error("should fail with Guid should contain 32 digits with 4 dashes message") } - _, err = store.Groups().GetByID("c5589d9f-8044-b000-5f6d-bcc9f93b8b8d").Get() + _, err = store.Groups().GetByID("c5589d9f-8044-b000-5f6d-bcc9f93b8b8d").Get(context.Background()) if err == nil { t.Error("should fail with object not found message") } @@ -441,7 +442,7 @@ func TestTaxonomyNotFoundIDs(t *testing.T) { }) t.Run("Sets/GetByID", func(t *testing.T) { - _, err := store.Sets().GetByID("wrong-id").Get() + _, err := store.Sets().GetByID("wrong-id").Get(context.Background()) if err == nil { t.Error("should fail with Guid should contain 32 digits with 4 dashes message") } @@ -449,7 +450,7 @@ func TestTaxonomyNotFoundIDs(t *testing.T) { t.Error("should fail with Guid should contain 32 digits with 4 dashes message") } - _, err = store.Sets().GetByID("c5589d9f-8044-b000-5f6d-bcc9f93b8b8d").Get() + _, err = store.Sets().GetByID("c5589d9f-8044-b000-5f6d-bcc9f93b8b8d").Get(context.Background()) if err == nil { t.Error("should fail with object not found message") } @@ -459,7 +460,7 @@ func TestTaxonomyNotFoundIDs(t *testing.T) { }) t.Run("Terms/GetByID", func(t *testing.T) { - _, err := store.Terms().GetByID("wrong-id").Get() + _, err := store.Terms().GetByID("wrong-id").Get(context.Background()) if err == nil { t.Error("should fail with Guid should contain 32 digits with 4 dashes message") } @@ -467,7 +468,7 @@ func TestTaxonomyNotFoundIDs(t *testing.T) { t.Error("should fail with Guid should contain 32 digits with 4 dashes message") } - _, err = store.Terms().GetByID("c5589d9f-8044-b000-5f6d-bcc9f93b8b8d").Get() + _, err = store.Terms().GetByID("c5589d9f-8044-b000-5f6d-bcc9f93b8b8d").Get(context.Background()) if err == nil { t.Error("should fail with object not found message") } @@ -507,7 +508,7 @@ func TestTaxonomyUtils(t *testing.T) { } func getTermGroupID(taxonomy *Taxonomy) (string, error) { - gs, err := taxonomy.Stores().Default().Groups().Get() + gs, err := taxonomy.Stores().Default().Groups().Get(context.Background()) if err != nil { return "", err } @@ -537,7 +538,7 @@ func getTermSetID(taxonomy *Taxonomy) (string, error) { return "", err } - tsData, err := termSets.Get() + tsData, err := termSets.Get(context.Background()) if err != nil { return "", err } @@ -564,7 +565,7 @@ func getTermID(taxonomy *Taxonomy) (string, error) { return "", err } - terms, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Select("Id").GetAllTerms() + terms, err := taxonomy.Stores().Default().Sets().GetByID(termSetGUID).Select("Id").GetAllTerms(context.Background()) if terms == nil { return "", err } diff --git a/api/pagination_test.go b/api/pagination_test.go index 5c5eb21..91e7cfe 100644 --- a/api/pagination_test.go +++ b/api/pagination_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -10,7 +11,7 @@ func TestPagination(t *testing.T) { sp := NewSP(spClient) t.Run("Items", func(t *testing.T) { - paged, err := sp.Web().GetList("_catalogs/masterpage").Items().Top(1).GetPaged() + paged, err := sp.Web().GetList("_catalogs/masterpage").Items().Top(1).GetPaged(context.Background()) if err != nil { t.Fatal(err) } diff --git a/api/profiles.go b/api/profiles.go index 1f5b336..304de13 100644 --- a/api/profiles.go +++ b/api/profiles.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "net/url" @@ -81,7 +82,7 @@ func NewProfiles(client *gosip.SPClient, endpoint string, config *RequestConfig) } // GetMyProperties gets current context user profile properties -func (profiles *Profiles) GetMyProperties() (ProfilePropsResp, error) { +func (profiles *Profiles) GetMyProperties(ctx context.Context) (ProfilePropsResp, error) { client := NewHTTPClient(profiles.client) apiURL, _ := url.Parse(profiles.endpoint + "/GetMyProperties") query := apiURL.Query() @@ -89,11 +90,11 @@ func (profiles *Profiles) GetMyProperties() (ProfilePropsResp, error) { query.Set(k, TrimMultiline(v)) } apiURL.RawQuery = query.Encode() - return client.Post(apiURL.String(), nil, profiles.config) + return client.Post(ctx, apiURL.String(), nil, profiles.config) } // GetPropertiesFor gets properties of a specified user profile (by user login name) -func (profiles *Profiles) GetPropertiesFor(loginName string) (ProfilePropsResp, error) { +func (profiles *Profiles) GetPropertiesFor(ctx context.Context, loginName string) (ProfilePropsResp, error) { client := NewHTTPClient(profiles.client) apiURL, _ := url.Parse( profiles.endpoint + @@ -104,17 +105,17 @@ func (profiles *Profiles) GetPropertiesFor(loginName string) (ProfilePropsResp, query.Set(k, TrimMultiline(v)) } apiURL.RawQuery = query.Encode() - return client.Get(apiURL.String(), profiles.config) + return client.Get(ctx, apiURL.String(), profiles.config) } // GetUserProfilePropertyFor gets specific property of a specified user profile (by user login name) -func (profiles *Profiles) GetUserProfilePropertyFor(loginName string, property string) (string, error) { +func (profiles *Profiles) GetUserProfilePropertyFor(ctx context.Context, loginName string, property string) (string, error) { client := NewHTTPClient(profiles.client) endpoint := profiles.endpoint + "/GetUserProfilePropertyFor(" + "accountname='" + url.QueryEscape(loginName) + "'," + "propertyname='" + url.QueryEscape(property) + "')" - data, err := client.Get(endpoint, profiles.config) + data, err := client.Get(ctx, endpoint, profiles.config) if err != nil { return "", err } @@ -134,7 +135,7 @@ func (profiles *Profiles) GetUserProfilePropertyFor(loginName string, property s } // GetOwnerUserProfile gets owner's user profile -func (profiles *Profiles) GetOwnerUserProfile() (ProfileResp, error) { +func (profiles *Profiles) GetOwnerUserProfile(ctx context.Context) (ProfileResp, error) { client := NewHTTPClient(profiles.client) apiURL, _ := url.Parse( getPriorEndpoint(profiles.endpoint, "/_api") + @@ -145,11 +146,11 @@ func (profiles *Profiles) GetOwnerUserProfile() (ProfileResp, error) { query.Set(k, TrimMultiline(v)) } apiURL.RawQuery = query.Encode() - return client.Post(apiURL.String(), nil, profiles.config) + return client.Post(ctx, apiURL.String(), nil, profiles.config) } // UserProfile gets current context user profile object -func (profiles *Profiles) UserProfile() (ProfileResp, error) { +func (profiles *Profiles) UserProfile(ctx context.Context) (ProfileResp, error) { client := NewHTTPClient(profiles.client) apiURL, _ := url.Parse( getPriorEndpoint(profiles.endpoint, "/_api") + @@ -160,11 +161,11 @@ func (profiles *Profiles) UserProfile() (ProfileResp, error) { query.Set(k, TrimMultiline(v)) } apiURL.RawQuery = query.Encode() - return client.Post(apiURL.String(), nil, profiles.config) + return client.Post(ctx, apiURL.String(), nil, profiles.config) } // SetSingleValueProfileProperty sets a single value property for the profile by its email -func (profiles *Profiles) SetSingleValueProfileProperty(loginName string, property string, value string) error { +func (profiles *Profiles) SetSingleValueProfileProperty(ctx context.Context, loginName string, property string, value string) error { client := NewHTTPClient(profiles.client) endpoint := profiles.endpoint + "/SetSingleValueProfileProperty" prop := map[string]string{} @@ -172,12 +173,12 @@ func (profiles *Profiles) SetSingleValueProfileProperty(loginName string, proper prop["propertyName"] = property prop["propertyValue"] = value body, _ := json.Marshal(prop) - _, err := client.Post(endpoint, bytes.NewBuffer(body), profiles.config) + _, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), profiles.config) return err } // SetMultiValuedProfileProperty sets a multi value property for the profile by its email -func (profiles *Profiles) SetMultiValuedProfileProperty(loginName string, property string, values []string) error { +func (profiles *Profiles) SetMultiValuedProfileProperty(ctx context.Context, loginName string, property string, values []string) error { client := NewHTTPClient(profiles.client) endpoint := profiles.endpoint + "/SetMultiValuedProfileProperty" prop := map[string]interface{}{} @@ -185,15 +186,15 @@ func (profiles *Profiles) SetMultiValuedProfileProperty(loginName string, proper prop["propertyName"] = property prop["propertyValues"] = values body, _ := json.Marshal(prop) - _, err := client.Post(endpoint, bytes.NewBuffer(body), profiles.config) + _, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), profiles.config) return err } // HideSuggestion removes the specified user from the user's list of suggested people to follow -func (profiles *Profiles) HideSuggestion(loginName string) ([]byte, error) { +func (profiles *Profiles) HideSuggestion(ctx context.Context, loginName string) ([]byte, error) { client := NewHTTPClient(profiles.client) endpoint := profiles.endpoint + "/HideSuggestion('" + url.QueryEscape(loginName) + "')" - return client.Post(endpoint, nil, profiles.config) + return client.Post(ctx, endpoint, nil, profiles.config) } // /* Response helpers */ diff --git a/api/profiles_test.go b/api/profiles_test.go index b1e0099..869406d 100644 --- a/api/profiles_test.go +++ b/api/profiles_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" ) @@ -10,13 +11,13 @@ func TestProfiles(t *testing.T) { sp := NewSP(spClient) profiles := sp.Profiles() - user, err := sp.Web().CurrentUser().Get() + user, err := sp.Web().CurrentUser().Get(context.Background()) if err != nil { t.Error(err) } t.Run("GetMyProperties", func(t *testing.T) { - profile, err := profiles.GetMyProperties() + profile, err := profiles.GetMyProperties(context.Background()) if err != nil { t.Error(err) } @@ -26,7 +27,7 @@ func TestProfiles(t *testing.T) { }) t.Run("GetPropertiesFor", func(t *testing.T) { - props, err := profiles.GetPropertiesFor(user.Data().LoginName) + props, err := profiles.GetPropertiesFor(context.Background(), user.Data().LoginName) if err != nil { t.Error(err) } @@ -40,7 +41,7 @@ func TestProfiles(t *testing.T) { t.Run("GetUserProfilePropertyFor", func(t *testing.T) { accountName, err := sp.Profiles().Conf(headers.verbose). - GetUserProfilePropertyFor(user.Data().LoginName, "AccountName") + GetUserProfilePropertyFor(context.Background(), user.Data().LoginName, "AccountName") if err != nil { t.Error(err) } @@ -49,7 +50,7 @@ func TestProfiles(t *testing.T) { } if envCode != "2013" { accountName, err = sp.Profiles().Conf(headers.minimalmetadata). - GetUserProfilePropertyFor(user.Data().LoginName, "AccountName") + GetUserProfilePropertyFor(context.Background(), user.Data().LoginName, "AccountName") if err != nil { t.Error(err) } @@ -57,7 +58,7 @@ func TestProfiles(t *testing.T) { t.Error("wrong property value") } accountName, err = sp.Profiles().Conf(headers.nometadata). - GetUserProfilePropertyFor(user.Data().LoginName, "AccountName") + GetUserProfilePropertyFor(context.Background(), user.Data().LoginName, "AccountName") if err != nil { t.Error(err) } @@ -68,7 +69,7 @@ func TestProfiles(t *testing.T) { }) t.Run("GetOwnerUserProfile", func(t *testing.T) { - profile, err := profiles.GetOwnerUserProfile() + profile, err := profiles.GetOwnerUserProfile(context.Background()) if err != nil { t.Error(err) } @@ -78,7 +79,7 @@ func TestProfiles(t *testing.T) { }) t.Run("UserProfile", func(t *testing.T) { - profile, err := profiles.UserProfile() + profile, err := profiles.UserProfile(context.Background()) if err != nil { t.Error(err) } @@ -91,24 +92,24 @@ func TestProfiles(t *testing.T) { }) t.Run("UserProfile", func(t *testing.T) { - profile, err := profiles.UserProfile() + profile, err := profiles.UserProfile(context.Background()) if err != nil { t.Error(err) } - if _, err := sp.Profiles().HideSuggestion(profile.Data().AccountName); err != nil { + if _, err := sp.Profiles().HideSuggestion(context.Background(), profile.Data().AccountName); err != nil { t.Error(err) } }) t.Run("SetSingleValueProfileProperty", func(t *testing.T) { - if err := profiles.SetSingleValueProfileProperty(user.Data().LoginName, "AboutMe", "Updated from Gosip"); err != nil { + if err := profiles.SetSingleValueProfileProperty(context.Background(), user.Data().LoginName, "AboutMe", "Updated from Gosip"); err != nil { t.Error(err) } }) t.Run("SetMultiValuedProfileProperty", func(t *testing.T) { tags := []string{"#ci", "#demo", "#test"} - if err := profiles.SetMultiValuedProfileProperty(user.Data().LoginName, "SPS-HashTags", tags); err != nil { + if err := profiles.SetMultiValuedProfileProperty(context.Background(), user.Data().LoginName, "SPS-HashTags", tags); err != nil { t.Error(err) } }) diff --git a/api/properties.go b/api/properties.go index a6c76a8..1b9ffb0 100644 --- a/api/properties.go +++ b/api/properties.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "reflect" @@ -43,13 +44,13 @@ func (properties *Properties) ToURL() string { } // Get gets properties collection -func (properties *Properties) Get() (PropsResp, error) { +func (properties *Properties) Get(ctx context.Context) (PropsResp, error) { client := NewHTTPClient(properties.client) - return client.Get(properties.ToURL(), properties.config) + return client.Get(ctx, properties.ToURL(), properties.config) } // GetProps gets specific props values -func (properties *Properties) GetProps(props []string) (map[string]string, error) { +func (properties *Properties) GetProps(ctx context.Context, props []string) (map[string]string, error) { for indx, prop := range props { key := strings.Replace(strings.Replace(prop, "_x005f_", "_", -1), "_", "_x005f_", -1) props[indx] = key @@ -62,10 +63,10 @@ func (properties *Properties) GetProps(props []string) (map[string]string, error } selectProps += prop } - res, err := scoped.Select(selectProps).Get() + res, err := scoped.Select(selectProps).Get(ctx) if err != nil { scoped.modifiers = &ODataMods{} - res, err := scoped.Get() + res, err := scoped.Get(ctx) if err != nil { return nil, err } @@ -87,36 +88,36 @@ func (properties *Properties) GetProps(props []string) (map[string]string, error } // Set sets a single property (CSOM helper) -func (properties *Properties) Set(prop string, value string) error { - return properties.SetProps(map[string]string{prop: value}) +func (properties *Properties) Set(ctx context.Context, prop string, value string) error { + return properties.SetProps(ctx, map[string]string{prop: value}) } // SetProps sets multiple properties defined in string map object (CSOM helper) -func (properties *Properties) SetProps(props map[string]string) error { +func (properties *Properties) SetProps(ctx context.Context, props map[string]string) error { if properties.entity == "web" { - return properties.setWebProps(props) + return properties.setWebProps(ctx, props) } if properties.entity == "folder" { - return properties.setFolderProps(props) + return properties.setFolderProps(ctx, props) } if properties.entity == "file" { - return properties.setFileProps(props) + return properties.setFileProps(ctx, props) } return fmt.Errorf("unknown parent entity %s", properties.entity) } // setWebProps sets multiple properties defined in string map object (CSOM helper) -func (properties *Properties) setWebProps(props map[string]string) error { +func (properties *Properties) setWebProps(ctx context.Context, props map[string]string) error { // ToDo: exclude extra call to site and web metadata web := NewWeb(properties.client, getPriorEndpoint(properties.endpoint, "/AllProperties"), properties.config) site := NewSP(properties.client).Site() - siteR, err := site.Select("Id").Get() + siteR, err := site.Select("Id").Get(ctx) if err != nil { return err } - webR, err := web.Select("Id").Get() + webR, err := web.Select("Id").Get(ctx) if err != nil { return err } @@ -139,14 +140,14 @@ func (properties *Properties) setWebProps(props map[string]string) error { } client := NewHTTPClient(properties.client) - _, err = client.ProcessQuery(properties.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), properties.config) + _, err = client.ProcessQuery(ctx, properties.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), properties.config) printNoScriptWarning(properties.endpoint, err) return err } // setFolderProps sets multiple properties defined in string map object (CSOM helper) -func (properties *Properties) setFolderProps(props map[string]string) error { +func (properties *Properties) setFolderProps(ctx context.Context, props map[string]string) error { // ToDo: exclude extra call to site, web and folder metadata identity := "" @@ -154,19 +155,19 @@ func (properties *Properties) setFolderProps(props map[string]string) error { folder := NewFolder(properties.client, getPriorEndpoint(properties.endpoint, "/Properties"), properties.config) site := NewSP(properties.client).Site() - siteR, err := site.Select("Id").Get() + siteR, err := site.Select("Id").Get(ctx) if err != nil { return err } identity = fmt.Sprintf("740c6a0b-85e2-48a0-a494-e0f1759d4aa7:site:%s", siteR.Data().ID) - webR, err := web.Select("Id").Get() + webR, err := web.Select("Id").Get(ctx) if err != nil { return err } identity = fmt.Sprintf("%s:web:%s", identity, webR.Data().ID) - folderR, err := folder.Select("UniqueId").Get() + folderR, err := folder.Select("UniqueId").Get(ctx) if err != nil { return err } @@ -188,17 +189,17 @@ func (properties *Properties) setFolderProps(props map[string]string) error { } client := NewHTTPClient(properties.client) - _, err = client.ProcessQuery(properties.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), properties.config) + _, err = client.ProcessQuery(ctx, properties.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), properties.config) printNoScriptWarning(properties.endpoint, err) return err } // setFileProps sets multiple properties defined in string map object (CSOM helper) -func (properties *Properties) setFileProps(props map[string]string) error { +func (properties *Properties) setFileProps(ctx context.Context, props map[string]string) error { file := NewFile(properties.client, getPriorEndpoint(properties.endpoint, "/Properties"), properties.config) - fileR, err := file.Select("UniqueId").Get() + fileR, err := file.Select("UniqueId").Get(ctx) if err != nil { return err } @@ -220,7 +221,7 @@ func (properties *Properties) setFileProps(props map[string]string) error { } client := NewHTTPClient(properties.client) - _, err = client.ProcessQuery(properties.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), properties.config) + _, err = client.ProcessQuery(ctx, properties.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), properties.config) printNoScriptWarning(properties.endpoint, err) return err diff --git a/api/properties_test.go b/api/properties_test.go index 26c387f..47d44ac 100644 --- a/api/properties_test.go +++ b/api/properties_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "strings" "testing" @@ -18,7 +19,7 @@ func TestProperties(t *testing.T) { t.Run("Constructor", func(t *testing.T) { p := NewProperties(spClient, endpoint, nil, "web") - if _, err := p.Select("vti_x005f_defaultlanguage").Get(); err != nil { + if _, err := p.Select("vti_x005f_defaultlanguage").Get(context.Background()); err != nil { t.Error(err) } }) @@ -38,7 +39,7 @@ func TestProperties(t *testing.T) { t.Skip("is not supported with SP 2013") } - data, err := webProps.Select("vti_x005f_defaultlanguage").Get() + data, err := webProps.Select("vti_x005f_defaultlanguage").Get(context.Background()) if err != nil { t.Error(err) } @@ -53,7 +54,7 @@ func TestProperties(t *testing.T) { }) t.Run("GetProps", func(t *testing.T) { - data, err := webProps.GetProps([]string{"vti_defaultlanguage"}) + data, err := webProps.GetProps(context.Background(), []string{"vti_defaultlanguage"}) if err != nil { t.Error(err) } @@ -64,7 +65,7 @@ func TestProperties(t *testing.T) { }) t.Run("GetMultipleProps", func(t *testing.T) { - data, err := webProps.GetProps([]string{"vti_defaultlanguage", "vti_associategroups"}) + data, err := webProps.GetProps(context.Background(), []string{"vti_defaultlanguage", "vti_associategroups"}) if err != nil { t.Error(err) } @@ -75,20 +76,20 @@ func TestProperties(t *testing.T) { }) t.Run("GetNonExistongProps", func(t *testing.T) { - _, err := webProps.GetProps([]string{"vti_defaultlanguage", "vti_associategroups_do_not_exist"}) + _, err := webProps.GetProps(context.Background(), []string{"vti_defaultlanguage", "vti_associategroups_do_not_exist"}) if err != nil { t.Error(err) } }) t.Run("Set", func(t *testing.T) { - if err := webProps.Set("test_gosip", time.Now().String()); err != nil { + if err := webProps.Set(context.Background(), "test_gosip", time.Now().String()); err != nil { // By default is denied on Modern SPO sites, so ignore in tests if !strings.Contains(err.Error(), "System.UnauthorizedAccessException") { t.Error(err) } } - if err := web.RootFolder().Props().Set("test_gosip", time.Now().String()); err != nil { + if err := web.RootFolder().Props().Set(context.Background(), "test_gosip", time.Now().String()); err != nil { // By default is denied on Modern SPO sites, so ignore in tests if !strings.Contains(err.Error(), "System.UnauthorizedAccessException") { t.Error(err) @@ -97,7 +98,7 @@ func TestProperties(t *testing.T) { }) t.Run("SetProps", func(t *testing.T) { - if err := webProps.SetProps(map[string]string{ + if err := webProps.SetProps(context.Background(), map[string]string{ "test_gosip_prop1": time.Now().String(), "test_gosip_prop2": time.Now().String(), }); err != nil { diff --git a/api/records.go b/api/records.go index 0f7cc60..8c4ee04 100644 --- a/api/records.go +++ b/api/records.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "strconv" @@ -23,7 +24,7 @@ func NewRecords(item *Item) *Records { } // IsRecord checks is current item is declared as a record -func (records *Records) IsRecord() (bool, error) { +func (records *Records) IsRecord(ctx context.Context) (bool, error) { // // It is better using REST and OData__vti_ItemDeclaredRecord field value // jsomResp, err := csomItemRecordMethod(records.item, "IsRecord", nil) // if err != nil { @@ -39,7 +40,7 @@ func (records *Records) IsRecord() (bool, error) { // } // return arrRes[2].(bool), nil - date, err := records.RecordDate() + date, err := records.RecordDate(ctx) if err != nil { return false, err } @@ -50,8 +51,8 @@ func (records *Records) IsRecord() (bool, error) { } // RecordDate checks record declaration date of this item -func (records *Records) RecordDate() (time.Time, error) { - data, err := records.item.Select("OData__vti_ItemDeclaredRecord").Get() +func (records *Records) RecordDate(ctx context.Context) (time.Time, error) { + data, err := records.item.Select("OData__vti_ItemDeclaredRecord").Get(ctx) if err != nil { if strings.Contains(err.Error(), "OData__vti_ItemDeclaredRecord") { return time.Time{}, nil // in place records is not configured in a list @@ -69,32 +70,32 @@ func (records *Records) RecordDate() (time.Time, error) { } // Declare declares this item as a record (CSOM helper) -func (records *Records) Declare() error { - _, err := csomItemRecordMethod(records.item, "DeclareItemAsRecord", nil, records.item.config) +func (records *Records) Declare(ctx context.Context) error { + _, err := csomItemRecordMethod(ctx, records.item, "DeclareItemAsRecord", nil, records.item.config) return err } // DeclareWithDate declares this item as a record with record declaration date (CSOM helper) -func (records *Records) DeclareWithDate(date time.Time) error { - _, err := csomItemRecordMethod(records.item, "DeclareItemAsRecordWithDeclarationDate", &date, records.item.config) +func (records *Records) DeclareWithDate(ctx context.Context, date time.Time) error { + _, err := csomItemRecordMethod(ctx, records.item, "DeclareItemAsRecordWithDeclarationDate", &date, records.item.config) return err } // Undeclare undeclared this item as a record (the item is not a record after an action is done) (CSOM helper) -func (records *Records) Undeclare() error { - _, err := csomItemRecordMethod(records.item, "UndeclareItemAsRecord", nil, records.item.config) +func (records *Records) Undeclare(ctx context.Context) error { + _, err := csomItemRecordMethod(ctx, records.item, "UndeclareItemAsRecord", nil, records.item.config) return err } // csomItemRecordMethod constructs CSOM API process query to cover missed REST API functionality -func csomItemRecordMethod(item *Item, csomStaticMethod string, date *time.Time, config *RequestConfig) ([]byte, error) { +func csomItemRecordMethod(ctx context.Context, item *Item, csomStaticMethod string, date *time.Time, config *RequestConfig) ([]byte, error) { client := NewHTTPClient(item.client) - itemR, err := item.Select("Id").Get() + itemR, err := item.Select("Id").Get(ctx) if err != nil { return nil, err } list := item.ParentList() - listR, err := list.Select("Id").Get() + listR, err := list.Select("Id").Get(ctx) if err != nil { return nil, err } @@ -123,7 +124,7 @@ func csomItemRecordMethod(item *Item, csomStaticMethod string, date *time.Time, return nil, err } - jsomResp, err := client.ProcessQuery(item.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), config) + jsomResp, err := client.ProcessQuery(ctx, item.client.AuthCnfg.GetSiteURL(), bytes.NewBuffer([]byte(csomPkg)), config) if err != nil { return nil, err } diff --git a/api/records_test.go b/api/records_test.go index 1836835..12ca0ac 100644 --- a/api/records_test.go +++ b/api/records_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "testing" "time" @@ -18,7 +19,7 @@ func TestRecords(t *testing.T) { sp := NewSP(spClient) // Activate in place record management feature - if err := sp.Site().Features().Add("da2e115b-07e4-49d9-bb2c-35e93bb9fca9", true); err != nil { + if err := sp.Site().Features().Add(context.Background(), "da2e115b-07e4-49d9-bb2c-35e93bb9fca9", true); err != nil { t.Error(err) } @@ -30,45 +31,45 @@ func TestRecords(t *testing.T) { fmt.Sprintf("%s.txt", uuid.New().String()), } - if _, err := folder.Folders().Add(folderName); err != nil { + if _, err := folder.Folders().Add(context.Background(), folderName); err != nil { t.Error(err) } for _, doc := range docs { - if _, err := folder.Folders().GetByName(folderName).Files().Add(doc, []byte(doc), true); err != nil { + if _, err := folder.Folders().GetByName(folderName).Files().Add(context.Background(), doc, []byte(doc), true); err != nil { t.Error(err) } } t.Run("Records/Declare", func(t *testing.T) { - item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[0]).GetItem() + item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[0]).GetItem(context.Background()) if err != nil { t.Error(err) } - if err := item.Records().Declare(); err != nil { + if err := item.Records().Declare(context.Background()); err != nil { t.Error(err) } }) t.Run("Records/IsRecord", func(t *testing.T) { - item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[0]).GetItem() + item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[0]).GetItem(context.Background()) if err != nil { t.Error(err) } - if _, err := item.Records().IsRecord(); err != nil { + if _, err := item.Records().IsRecord(context.Background()); err != nil { t.Error(err) } }) t.Run("Records/Undeclare", func(t *testing.T) { - item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[0]).GetItem() + item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[0]).GetItem(context.Background()) if err != nil { t.Error(err) } - if err := item.Records().Undeclare(); err != nil { + if err := item.Records().Undeclare(context.Background()); err != nil { t.Error(err) } - recDate, err := item.Records().RecordDate() + recDate, err := item.Records().RecordDate(context.Background()) if err != nil { t.Error(err) } @@ -82,16 +83,16 @@ func TestRecords(t *testing.T) { t.Skip("is not supported with old SharePoint versions") } - item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[1]).GetItem() + item, err := folder.Folders().GetByName(folderName).Files().GetByName(docs[1]).GetItem(context.Background()) if err != nil { t.Error(err) } strTime := "2019-01-01T08:00:00.000Z" date, _ := time.Parse(time.RFC3339, strTime) - if err := item.Records().DeclareWithDate(date); err != nil { + if err := item.Records().DeclareWithDate(context.Background(), date); err != nil { t.Error(err) } - recDate, err := item.Records().RecordDate() + recDate, err := item.Records().RecordDate(context.Background()) if err != nil { t.Error(err) } @@ -99,12 +100,12 @@ func TestRecords(t *testing.T) { t.Error("wrong record date") } // Undeclare to delete after tests - if err := item.Records().Undeclare(); err != nil { + if err := item.Records().Undeclare(context.Background()); err != nil { t.Error(err) } }) - if err := folder.Folders().GetByName(folderName).Delete(); err != nil { + if err := folder.Folders().GetByName(folderName).Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/recycleBin.go b/api/recycleBin.go index 264c91e..5e560cc 100644 --- a/api/recycleBin.go +++ b/api/recycleBin.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "time" @@ -57,9 +58,9 @@ func (recycleBin *RecycleBin) ToURL() string { } // Get gets recycled items queryable collection -func (recycleBin *RecycleBin) Get() (RecycleBinResp, error) { +func (recycleBin *RecycleBin) Get(ctx context.Context) (RecycleBinResp, error) { client := NewHTTPClient(recycleBin.client) - return client.Get(recycleBin.ToURL(), recycleBin.config) + return client.Get(ctx, recycleBin.ToURL(), recycleBin.config) } // GetByID gets a recycled item by its ID @@ -96,15 +97,15 @@ func NewRecycleBinItem(client *gosip.SPClient, endpoint string, config *RequestC } // Get gets this recycle item data object -func (recycleBinItem *RecycleBinItem) Get() (RecycleBinItemResp, error) { +func (recycleBinItem *RecycleBinItem) Get(ctx context.Context) (RecycleBinItemResp, error) { client := NewHTTPClient(recycleBinItem.client) - return client.Get(recycleBinItem.endpoint, recycleBinItem.config) + return client.Get(ctx, recycleBinItem.endpoint, recycleBinItem.config) } // Restore restores this recycled item -func (recycleBinItem *RecycleBinItem) Restore() error { +func (recycleBinItem *RecycleBinItem) Restore(ctx context.Context) error { endpoint := fmt.Sprintf("%s/Restore()", recycleBinItem.endpoint) client := NewHTTPClient(recycleBinItem.client) - _, err := client.Post(endpoint, nil, recycleBinItem.config) + _, err := client.Post(ctx, endpoint, nil, recycleBinItem.config) return err } diff --git a/api/recycleBin_test.go b/api/recycleBin_test.go index a7afad1..98b3470 100644 --- a/api/recycleBin_test.go +++ b/api/recycleBin_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" "github.com/google/uuid" @@ -12,13 +13,13 @@ func TestRecycleBin(t *testing.T) { sp := NewSP(spClient) newListTitle := uuid.New().String() - if _, err := sp.Web().Lists().Add(newListTitle, nil); err != nil { + if _, err := sp.Web().Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Error(err) } list := sp.Web().Lists().GetByTitle(newListTitle) t.Run("Get/Site", func(t *testing.T) { - data, err := sp.Site().RecycleBin().Top(1).Get() + data, err := sp.Site().RecycleBin().Top(1).Get(context.Background()) if err != nil { t.Error(err) } @@ -28,32 +29,32 @@ func TestRecycleBin(t *testing.T) { }) t.Run("Get/Web", func(t *testing.T) { - _, err := sp.Web().RecycleBin().Top(1).Get() + _, err := sp.Web().RecycleBin().Top(1).Get(context.Background()) if err != nil { t.Error(err) } }) t.Run("Restore", func(t *testing.T) { - data, err := list.Items().Add([]byte(`{"Title":"Item"}`)) + data, err := list.Items().Add(context.Background(), []byte(`{"Title":"Item"}`)) if err != nil { t.Error(err) } - if err := list.Items().GetByID(data.Data().ID).Recycle(); err != nil { + if err := list.Items().GetByID(data.Data().ID).Recycle(context.Background()); err != nil { t.Error(err) } - items, err := sp.Web().RecycleBin().OrderBy("DeletedDate", false).Filter("LeafName eq '1_.000'").Top(1).Get() + items, err := sp.Web().RecycleBin().OrderBy("DeletedDate", false).Filter("LeafName eq '1_.000'").Top(1).Get(context.Background()) if err != nil { t.Error(err) } itemID := items.Data()[0].Data().ID - if _, err := sp.Web().RecycleBin().GetByID(itemID).Get(); err != nil { + if _, err := sp.Web().RecycleBin().GetByID(itemID).Get(context.Background()); err != nil { t.Error(err) } - if err := sp.Web().RecycleBin().GetByID(itemID).Restore(); err != nil { + if err := sp.Web().RecycleBin().GetByID(itemID).Restore(context.Background()); err != nil { t.Error(err) } - data2, err := list.Items().Select("Id").Get() + data2, err := list.Items().Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -62,7 +63,7 @@ func TestRecycleBin(t *testing.T) { } }) - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Error(err) } diff --git a/api/roleDef.go b/api/roleDef.go index b928534..12fdd70 100644 --- a/api/roleDef.go +++ b/api/roleDef.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" @@ -36,27 +37,27 @@ type RoleDefInfo struct { } // GetByID gets a role definition by its ID -func (def *RoleDefinitions) GetByID(roleDefID int) (*RoleDefInfo, error) { +func (def *RoleDefinitions) GetByID(ctx context.Context, roleDefID int) (*RoleDefInfo, error) { endpoint := fmt.Sprintf("%s/GetById(%d)", def.endpoint, roleDefID) - return getRoleDef(def, endpoint) + return getRoleDef(ctx, def, endpoint) } // GetByName gets a role definition by its Name -func (def *RoleDefinitions) GetByName(roleDefName string) (*RoleDefInfo, error) { +func (def *RoleDefinitions) GetByName(ctx context.Context, roleDefName string) (*RoleDefInfo, error) { endpoint := fmt.Sprintf("%s/GetByName('%s')", def.endpoint, roleDefName) - return getRoleDef(def, endpoint) + return getRoleDef(ctx, def, endpoint) } // GetByType gets a role definition by its RoleTypeKinds -func (def *RoleDefinitions) GetByType(roleTypeKind int) (*RoleDefInfo, error) { +func (def *RoleDefinitions) GetByType(ctx context.Context, roleTypeKind int) (*RoleDefInfo, error) { endpoint := fmt.Sprintf("%s/GetByType(%d)", def.endpoint, roleTypeKind) - return getRoleDef(def, endpoint) + return getRoleDef(ctx, def, endpoint) } // Get gets a collection of available role definitions -func (def *RoleDefinitions) Get() ([]*RoleDefInfo, error) { +func (def *RoleDefinitions) Get(ctx context.Context) ([]*RoleDefInfo, error) { client := NewHTTPClient(def.client) - data, err := client.Get(def.endpoint, def.config) + data, err := client.Get(ctx, def.endpoint, def.config) if err != nil { return nil, err } @@ -75,10 +76,10 @@ func (def *RoleDefinitions) Get() ([]*RoleDefInfo, error) { return res.D.Results, nil } -func getRoleDef(def *RoleDefinitions, endpoint string) (*RoleDefInfo, error) { +func getRoleDef(ctx context.Context, def *RoleDefinitions, endpoint string) (*RoleDefInfo, error) { client := NewHTTPClient(def.client) - data, err := client.Post(endpoint, nil, patchConfigHeaders(def.config, HeadersPresets.Verbose.Headers)) + data, err := client.Post(ctx, endpoint, nil, patchConfigHeaders(def.config, HeadersPresets.Verbose.Headers)) if err != nil { return nil, err } diff --git a/api/roleDef_test.go b/api/roleDef_test.go index 661cffe..5b9b59e 100644 --- a/api/roleDef_test.go +++ b/api/roleDef_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -11,7 +12,7 @@ func TestRoleDefinitions(t *testing.T) { roleDef := &RoleDefInfo{} t.Run("GetByType", func(t *testing.T) { - res, err := web.RoleDefinitions().GetByType(RoleTypeKinds.Contributor) + res, err := web.RoleDefinitions().GetByType(context.Background(), RoleTypeKinds.Contributor) if err != nil { t.Error(err) } @@ -26,7 +27,7 @@ func TestRoleDefinitions(t *testing.T) { t.Skip("no role definition ID provided") } - res, err := web.RoleDefinitions().GetByID(roleDef.ID) + res, err := web.RoleDefinitions().GetByID(context.Background(), roleDef.ID) if err != nil { t.Error(err) } @@ -41,7 +42,7 @@ func TestRoleDefinitions(t *testing.T) { t.Skip("no role definition Name provided") } - res, err := web.RoleDefinitions().GetByName(roleDef.Name) + res, err := web.RoleDefinitions().GetByName(context.Background(), roleDef.Name) if err != nil { t.Error(err) } @@ -52,7 +53,7 @@ func TestRoleDefinitions(t *testing.T) { }) t.Run("Get", func(t *testing.T) { - res, err := web.RoleDefinitions().Get() + res, err := web.RoleDefinitions().Get(context.Background()) if err != nil { t.Error(err) } diff --git a/api/roles.go b/api/roles.go index 910e04d..fa455aa 100644 --- a/api/roles.go +++ b/api/roles.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" @@ -46,10 +47,10 @@ func NewRoles(client *gosip.SPClient, endpoint string, config *RequestConfig) *R } // HasUniqueAssignments checks is a securable object has unique permissions -func (permissions *Roles) HasUniqueAssignments() (bool, error) { +func (permissions *Roles) HasUniqueAssignments(ctx context.Context) (bool, error) { client := NewHTTPClient(permissions.client) endpoint := fmt.Sprintf("%s/HasUniqueRoleAssignments", permissions.endpoint) - data, err := client.Post(endpoint, nil, permissions.config) + data, err := client.Post(ctx, endpoint, nil, permissions.config) if err != nil { return false, err } @@ -65,17 +66,17 @@ func (permissions *Roles) HasUniqueAssignments() (bool, error) { } // ResetInheritance resets permissions inheritance for this securable object -func (permissions *Roles) ResetInheritance() error { +func (permissions *Roles) ResetInheritance(ctx context.Context) error { client := NewHTTPClient(permissions.client) endpoint := fmt.Sprintf("%s/ResetRoleInheritance", permissions.endpoint) - _, err := client.Post(endpoint, nil, permissions.config) + _, err := client.Post(ctx, endpoint, nil, permissions.config) return err } // BreakInheritance breaks permissions inheritance for this securable object // `copyRoleAssignments` - if true the permissions are copied from the current parent scope // `clearSubScopes` - true to make all child securable objects inherit role assignments from the current object -func (permissions *Roles) BreakInheritance(copyRoleAssignments bool, clearSubScopes bool) error { +func (permissions *Roles) BreakInheritance(ctx context.Context, copyRoleAssignments bool, clearSubScopes bool) error { client := NewHTTPClient(permissions.client) endpoint := fmt.Sprintf( "%s/BreakRoleInheritance(copyroleassignments=%t,clearsubscopes=%t)", @@ -83,14 +84,14 @@ func (permissions *Roles) BreakInheritance(copyRoleAssignments bool, clearSubSco copyRoleAssignments, clearSubScopes, ) - _, err := client.Post(endpoint, nil, permissions.config) + _, err := client.Post(ctx, endpoint, nil, permissions.config) return err } // AddAssigment adds role assigment for this securable object. Relevant only for the objects after breaking inheritance. // `principalID` - Principal ID - numeric ID from User information list - user or group ID // `roleDefID` - Role definition ID, use RoleDefinitions API for getting roleDefID -func (permissions *Roles) AddAssigment(principalID int, roleDefID int) error { +func (permissions *Roles) AddAssigment(ctx context.Context, principalID int, roleDefID int) error { client := NewHTTPClient(permissions.client) endpoint := fmt.Sprintf( "%s/RoleAssignments/AddRoleAssignment(principalid=%d,roledefid=%d)", @@ -98,14 +99,14 @@ func (permissions *Roles) AddAssigment(principalID int, roleDefID int) error { principalID, roleDefID, ) - _, err := client.Post(endpoint, nil, permissions.config) + _, err := client.Post(ctx, endpoint, nil, permissions.config) return err } // RemoveAssigment removes specified role assigment for a principal for this securable object. // `principalID` - Principal ID - numeric ID from User information list - user or group ID // `roleDefID` - Role definition ID, use RoleDefinitions API for getting roleDefID -func (permissions *Roles) RemoveAssigment(principalID int, roleDefID int) error { +func (permissions *Roles) RemoveAssigment(ctx context.Context, principalID int, roleDefID int) error { client := NewHTTPClient(permissions.client) endpoint := fmt.Sprintf( "%s/RoleAssignments/RemoveRoleAssignment(principalid=%d,roledefid=%d)", @@ -113,7 +114,7 @@ func (permissions *Roles) RemoveAssigment(principalID int, roleDefID int) error principalID, roleDefID, ) - _, err := client.Post(endpoint, nil, permissions.config) + _, err := client.Post(ctx, endpoint, nil, permissions.config) return err } diff --git a/api/roles_test.go b/api/roles_test.go index 5ab159b..4945acc 100644 --- a/api/roles_test.go +++ b/api/roles_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "testing" @@ -14,7 +15,7 @@ func TestRoles(t *testing.T) { newListTitle := uuid.New().String() // Pre-configuration - if _, err := web.Lists().Add(newListTitle, nil); err != nil { + if _, err := web.Lists().Add(context.Background(), newListTitle, nil); err != nil { t.Errorf("can't create a list to test permissions: %s", err) } list := web.Lists().GetByTitle(newListTitle) @@ -22,20 +23,20 @@ func TestRoles(t *testing.T) { if err != nil { t.Error(err) } - roleDef, err := web.RoleDefinitions().GetByType(RoleTypeKinds.Contributor) + roleDef, err := web.RoleDefinitions().GetByType(context.Background(), RoleTypeKinds.Contributor) if err != nil { t.Error(err) } t.Run("BreakInheritance", func(t *testing.T) { - if err := list.Roles().BreakInheritance(false, true); err != nil { + if err := list.Roles().BreakInheritance(context.Background(), false, true); err != nil { t.Error(err) } }) t.Run("HasUniqueAssignments", func(t *testing.T) { - _ = list.Roles().BreakInheritance(false, true) - hasUniqueAssignments, err := list.Roles().HasUniqueAssignments() + _ = list.Roles().BreakInheritance(context.Background(), false, true) + hasUniqueAssignments, err := list.Roles().HasUniqueAssignments(context.Background()) if err != nil { t.Error(err) } @@ -45,25 +46,25 @@ func TestRoles(t *testing.T) { }) t.Run("AddAssigment", func(t *testing.T) { - if err := list.Roles().AddAssigment(userID, roleDef.ID); err != nil { + if err := list.Roles().AddAssigment(context.Background(), userID, roleDef.ID); err != nil { t.Error(err) } }) t.Run("RemoveAssigment", func(t *testing.T) { - if err := list.Roles().RemoveAssigment(userID, roleDef.ID); err != nil { + if err := list.Roles().RemoveAssigment(context.Background(), userID, roleDef.ID); err != nil { t.Error(err) } }) t.Run("ResetInheritance", func(t *testing.T) { - if err := list.Roles().ResetInheritance(); err != nil { + if err := list.Roles().ResetInheritance(context.Background()); err != nil { t.Error(err) } }) // Post-configurations - if err := list.Delete(); err != nil { + if err := list.Delete(context.Background()); err != nil { t.Errorf("can't delete a list: %s", err) } @@ -71,7 +72,7 @@ func TestRoles(t *testing.T) { func getCurrentUserID() (int, error) { web := NewSP(spClient).Web() - data, err := web.CurrentUser().Select("Id").Conf(headers.verbose).Get() + data, err := web.CurrentUser().Select("Id").Conf(headers.verbose).Get(context.Background()) if err != nil { return 0, err } diff --git a/api/search.go b/api/search.go index 0929a07..e2e52f4 100644 --- a/api/search.go +++ b/api/search.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "reflect" @@ -153,7 +154,7 @@ func NewSearch(client *gosip.SPClient, endpoint string, config *RequestConfig) * } // PostQuery gets search results based on a `query` -func (search *Search) PostQuery(query *SearchQuery) (SearchResp, error) { +func (search *Search) PostQuery(ctx context.Context, query *SearchQuery) (SearchResp, error) { endpoint := fmt.Sprintf("%s/PostQuery", search.endpoint) client := NewHTTPClient(search.client) @@ -198,7 +199,7 @@ func (search *Search) PostQuery(query *SearchQuery) (SearchResp, error) { "Content-Type": "application/json;odata=verbose;charset=utf-8", } - return client.Post(endpoint, bytes.NewBuffer(body), patchConfigHeaders(search.config, headers)) + return client.Post(ctx, endpoint, bytes.NewBuffer(body), patchConfigHeaders(search.config, headers)) } // ToDo: diff --git a/api/search_test.go b/api/search_test.go index 3e9ec56..9ffe15a 100644 --- a/api/search_test.go +++ b/api/search_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" ) @@ -10,7 +11,7 @@ func TestSearch(t *testing.T) { t.Run("Basic", func(t *testing.T) { sp := NewSP(spClient) - data, err := sp.Search().PostQuery(&SearchQuery{ + data, err := sp.Search().PostQuery(context.Background(), &SearchQuery{ QueryText: "*", RowLimit: 10, }) @@ -24,7 +25,7 @@ func TestSearch(t *testing.T) { t.Run("Unmarshal", func(t *testing.T) { sp := NewSP(spClient) - res, err := sp.Search().PostQuery(&SearchQuery{ + res, err := sp.Search().PostQuery(context.Background(), &SearchQuery{ QueryText: "*", RowLimit: 10, }) @@ -38,7 +39,7 @@ func TestSearch(t *testing.T) { t.Run("Results", func(t *testing.T) { sp := NewSP(spClient) - res, err := sp.Search().PostQuery(&SearchQuery{ + res, err := sp.Search().PostQuery(context.Background(), &SearchQuery{ QueryText: "*", RowLimit: 10, }) diff --git a/api/site.go b/api/site.go index 337154e..245e07d 100644 --- a/api/site.go +++ b/api/site.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "strings" @@ -88,23 +89,23 @@ func (site *Site) FromURL(url string) *Site { } // Get gets this Site data object -func (site *Site) Get() (SiteResp, error) { +func (site *Site) Get(ctx context.Context) (SiteResp, error) { client := NewHTTPClient(site.client) - return client.Get(site.ToURL(), site.config) + return client.Get(ctx, site.ToURL(), site.config) } // Update updates Site's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.Site object -func (site *Site) Update(body []byte) (SiteResp, error) { +func (site *Site) Update(ctx context.Context, body []byte) (SiteResp, error) { body = patchMetadataType(body, "SP.Site") client := NewHTTPClient(site.client) - return client.Update(site.endpoint, bytes.NewBuffer(body), site.config) + return client.Update(ctx, site.endpoint, bytes.NewBuffer(body), site.config) } // Delete deletes current site (can't be restored from a recycle bin) -func (site *Site) Delete() error { +func (site *Site) Delete(ctx context.Context) error { client := NewHTTPClient(site.client) - _, err := client.Delete(site.endpoint, site.config) + _, err := client.Delete(ctx, site.endpoint, site.config) return err } @@ -115,15 +116,15 @@ func (site *Site) RootWeb() *Web { } // OpenWebByID gets a Web data object by its ID (GUID) -func (site *Site) OpenWebByID(webID string) (WebResp, error) { +func (site *Site) OpenWebByID(ctx context.Context, webID string) (WebResp, error) { endpoint := fmt.Sprintf("%s/OpenWebById('%s')", site.endpoint, webID) client := NewHTTPClient(site.client) - return client.Post(endpoint, nil, site.config) + return client.Post(ctx, endpoint, nil, site.config) } // WebByID gets a Web API object by its ID (GUID) -func (site *Site) WebByID(webID string) (*Web, error) { - w, err := site.OpenWebByID(webID) +func (site *Site) WebByID(ctx context.Context, webID string) (*Web, error) { + w, err := site.OpenWebByID(ctx, webID) if err != nil { return nil, err } diff --git a/api/site_test.go b/api/site_test.go index 6549b37..694c4d9 100644 --- a/api/site_test.go +++ b/api/site_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" ) @@ -14,7 +15,7 @@ func TestSite(t *testing.T) { t.Run("Constructor", func(t *testing.T) { s := NewSite(spClient, endpoint, nil) - if _, err := s.Select("Id").Get(); err != nil { + if _, err := s.Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) @@ -30,7 +31,7 @@ func TestSite(t *testing.T) { }) t.Run("GetURL", func(t *testing.T) { - data, err := site.Select("Url").Conf(headers.verbose).Get() + data, err := site.Select("Url").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -50,7 +51,7 @@ func TestSite(t *testing.T) { }) t.Run("RootWeb", func(t *testing.T) { - data, err := site.RootWeb().Select("Title").Conf(headers.verbose).Get() + data, err := site.RootWeb().Select("Title").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -60,7 +61,7 @@ func TestSite(t *testing.T) { }) t.Run("OpenWebByID", func(t *testing.T) { - data0, err := site.RootWeb().Select("Id").Conf(headers.verbose).Get() + data0, err := site.RootWeb().Select("Id").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -68,7 +69,7 @@ func TestSite(t *testing.T) { t.Error("can't get root web id property") } - data, err := site.OpenWebByID(data0.Data().ID) + data, err := site.OpenWebByID(context.Background(), data0.Data().ID) if err != nil { t.Error(err) } @@ -78,7 +79,7 @@ func TestSite(t *testing.T) { }) t.Run("WebByID", func(t *testing.T) { - data0, err := site.RootWeb().Select("Id").Conf(headers.verbose).Get() + data0, err := site.RootWeb().Select("Id").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -86,11 +87,11 @@ func TestSite(t *testing.T) { t.Error("can't get root web id property") } - web, err := site.WebByID(data0.Data().ID) + web, err := site.WebByID(context.Background(), data0.Data().ID) if err != nil { t.Error(err) } - data, err := web.Get() + data, err := web.Get(context.Background()) if err != nil { t.Error(err) } @@ -100,7 +101,7 @@ func TestSite(t *testing.T) { }) t.Run("Owner", func(t *testing.T) { - if _, err := site.Owner().Get(); err != nil { + if _, err := site.Owner().Get(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/sp.go b/api/sp.go index af2fe37..77b1276 100644 --- a/api/sp.go +++ b/api/sp.go @@ -2,6 +2,7 @@ package api import ( + "context" "fmt" "time" @@ -77,14 +78,15 @@ func (sp *SP) Taxonomy() *Taxonomy { } // ContextInfo gets current Context Info object data -func (sp *SP) ContextInfo() (*ContextInfo, error) { - return NewContext(sp.client, sp.ToURL(), sp.config).Get() +func (sp *SP) ContextInfo(ctx context.Context) (*ContextInfo, error) { + return NewContext(sp.client, sp.ToURL(), sp.config).Get(ctx) } // Metadata returns $metadata info -func (sp *SP) Metadata() ([]byte, error) { +func (sp *SP) Metadata(ctx context.Context) ([]byte, error) { client := NewHTTPClient(sp.client) return client.Get( + ctx, fmt.Sprintf("%s/_api/$metadata", sp.ToURL()), sp.config, ) diff --git a/api/sp_test.go b/api/sp_test.go index ca63cb8..18d3a3f 100644 --- a/api/sp_test.go +++ b/api/sp_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -62,7 +63,7 @@ func TestSP(t *testing.T) { t.Run("Metadata", func(t *testing.T) { sp := NewSP(spClient) - if _, err := sp.Metadata(); err != nil { + if _, err := sp.Metadata(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/subscriptions.go b/api/subscriptions.go index 116d330..d09f538 100644 --- a/api/subscriptions.go +++ b/api/subscriptions.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "time" @@ -64,9 +65,9 @@ func NewSubscription(client *gosip.SPClient, endpoint string, config *RequestCon } // Get gets list subscriptions response collection -func (subscriptions *Subscriptions) Get() ([]*SubscriptionInfo, error) { +func (subscriptions *Subscriptions) Get(ctx context.Context) ([]*SubscriptionInfo, error) { client := NewHTTPClient(subscriptions.client) - resp, err := client.Get(subscriptions.endpoint, subscriptions.config) + resp, err := client.Get(ctx, subscriptions.endpoint, subscriptions.config) if err != nil { return nil, err } @@ -88,7 +89,7 @@ func (subscriptions *Subscriptions) GetByID(subscriptionID string) *Subscription } // Add adds/updates new subscription to a list -func (subscriptions *Subscriptions) Add(notificationURL string, expiration time.Time, clientState string) (*SubscriptionInfo, error) { +func (subscriptions *Subscriptions) Add(ctx context.Context, notificationURL string, expiration time.Time, clientState string) (*SubscriptionInfo, error) { client := NewHTTPClient(subscriptions.client) payload := map[string]interface{}{ "notificationUrl": notificationURL, @@ -103,7 +104,7 @@ func (subscriptions *Subscriptions) Add(notificationURL string, expiration time. conf := patchConfigHeaders(subscriptions.config, map[string]string{ "Content-Type": "application/json", }) - resp, err := client.Post(subscriptions.endpoint, bytes.NewBuffer(body), conf) + resp, err := client.Post(ctx, subscriptions.endpoint, bytes.NewBuffer(body), conf) if err != nil { return nil, err } @@ -116,9 +117,9 @@ func (subscriptions *Subscriptions) Add(notificationURL string, expiration time. } // Get gets subscription info -func (subscription *Subscription) Get() (*SubscriptionInfo, error) { +func (subscription *Subscription) Get(ctx context.Context) (*SubscriptionInfo, error) { client := NewHTTPClient(subscription.client) - resp, err := client.Get(subscription.endpoint, subscription.config) + resp, err := client.Get(ctx, subscription.endpoint, subscription.config) if err != nil { return nil, err } @@ -126,14 +127,14 @@ func (subscription *Subscription) Get() (*SubscriptionInfo, error) { } // Delete deletes a subscription by its ID (GUID) -func (subscription *Subscription) Delete() error { +func (subscription *Subscription) Delete(ctx context.Context) error { client := NewHTTPClient(subscription.client) - _, err := client.Delete(subscription.endpoint, subscription.config) + _, err := client.Delete(ctx, subscription.endpoint, subscription.config) return err } // Update updates a subscription -func (subscription *Subscription) Update(metadata map[string]interface{}) (*SubscriptionInfo, error) { +func (subscription *Subscription) Update(ctx context.Context, metadata map[string]interface{}) (*SubscriptionInfo, error) { client := NewHTTPClient(subscription.client) body, err := json.Marshal(metadata) if err != nil { @@ -142,29 +143,29 @@ func (subscription *Subscription) Update(metadata map[string]interface{}) (*Subs conf := patchConfigHeaders(subscription.config, map[string]string{ "Content-Type": "application/json", }) - if _, err := client.Update(subscription.endpoint, bytes.NewBuffer(body), conf); err != nil { + if _, err := client.Update(ctx, subscription.endpoint, bytes.NewBuffer(body), conf); err != nil { return nil, err } - return subscription.Get() + return subscription.Get(ctx) } // SetExpiration sets new expiration datetime -func (subscription *Subscription) SetExpiration(expiration time.Time) (*SubscriptionInfo, error) { - return subscription.Update(map[string]interface{}{ +func (subscription *Subscription) SetExpiration(ctx context.Context, expiration time.Time) (*SubscriptionInfo, error) { + return subscription.Update(ctx, map[string]interface{}{ "expirationDateTime": expiration, }) } // SetNotificationURL sets new notification URL state -func (subscription *Subscription) SetNotificationURL(notificationURL string) (*SubscriptionInfo, error) { - return subscription.Update(map[string]interface{}{ +func (subscription *Subscription) SetNotificationURL(ctx context.Context, notificationURL string) (*SubscriptionInfo, error) { + return subscription.Update(ctx, map[string]interface{}{ "notificationUrl": notificationURL, }) } // SetClientState sets new client state -func (subscription *Subscription) SetClientState(clientState string) (*SubscriptionInfo, error) { - return subscription.Update(map[string]interface{}{ +func (subscription *Subscription) SetClientState(ctx context.Context, clientState string) (*SubscriptionInfo, error) { + return subscription.Update(ctx, map[string]interface{}{ "clientState": clientState, }) } diff --git a/api/subscriptions_test.go b/api/subscriptions_test.go index 431b315..fbbda6c 100644 --- a/api/subscriptions_test.go +++ b/api/subscriptions_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "os" "testing" "time" @@ -24,7 +25,7 @@ func TestSubscriptions(t *testing.T) { t.Run("Add", func(t *testing.T) { expiration := time.Now().Add(60 * time.Second) - sub, err := list.Subscriptions().Add(notificationURL, expiration, "") + sub, err := list.Subscriptions().Add(context.Background(), notificationURL, expiration, "") if err != nil { t.Error(err) return @@ -38,20 +39,20 @@ func TestSubscriptions(t *testing.T) { t.Run("Add#ExpirationInThePast", func(t *testing.T) { expiration := time.Now().AddDate(0, 0, -1) - if _, err := list.Subscriptions().Add(notificationURL, expiration, ""); err == nil { + if _, err := list.Subscriptions().Add(context.Background(), notificationURL, expiration, ""); err == nil { t.Error("should fail due to expiration limitation 'not in the past'") } }) t.Run("Add#MoreThan6Months", func(t *testing.T) { expiration := time.Now().AddDate(0, 6, 10) - if _, err := list.Subscriptions().Add(notificationURL, expiration, ""); err == nil { + if _, err := list.Subscriptions().Add(context.Background(), notificationURL, expiration, ""); err == nil { t.Error("should fail due to expiration limitation 'no more than 6 month'") } }) t.Run("GetByID", func(t *testing.T) { - sub, err := list.Subscriptions().GetByID(subID).Get() + sub, err := list.Subscriptions().GetByID(subID).Get(context.Background()) if err != nil { t.Error(err) return @@ -64,19 +65,19 @@ func TestSubscriptions(t *testing.T) { }) t.Run("GetByID#WrongID", func(t *testing.T) { - if _, err := list.Subscriptions().GetByID("WrongID").Get(); err == nil { + if _, err := list.Subscriptions().GetByID("WrongID").Get(context.Background()); err == nil { t.Error("should fail with wrong id") } }) t.Run("SetExpiration", func(t *testing.T) { - sub, err := list.Subscriptions().GetByID(subID).Get() + sub, err := list.Subscriptions().GetByID(subID).Get(context.Background()) if err != nil { t.Error(err) return } newExpiration := sub.ExpirationDateTime.Add(60 * time.Second) - subUpd, err := list.Subscriptions().GetByID(subID).SetExpiration(newExpiration) + subUpd, err := list.Subscriptions().GetByID(subID).SetExpiration(context.Background(), newExpiration) if err != nil { t.Error(err) return @@ -87,7 +88,7 @@ func TestSubscriptions(t *testing.T) { }) t.Run("SetClientState", func(t *testing.T) { - subUpd, err := list.Subscriptions().GetByID(subID).SetClientState("client state") + subUpd, err := list.Subscriptions().GetByID(subID).SetClientState(context.Background(), "client state") if err != nil { t.Error(err) return @@ -98,13 +99,13 @@ func TestSubscriptions(t *testing.T) { }) t.Run("SetNotificationURL#WrongURL", func(t *testing.T) { - if _, err := list.Subscriptions().GetByID(subID).SetNotificationURL("wrong-url"); err == nil { + if _, err := list.Subscriptions().GetByID(subID).SetNotificationURL(context.Background(), "wrong-url"); err == nil { t.Error("should fail with wrong URL") } }) t.Run("GetSubscriptions", func(t *testing.T) { - sub, err := list.Subscriptions().Get() + sub, err := list.Subscriptions().Get(context.Background()) if err != nil { t.Error(err) } @@ -114,16 +115,16 @@ func TestSubscriptions(t *testing.T) { }) t.Run("Delete", func(t *testing.T) { - resp, err := list.Subscriptions().Get() + resp, err := list.Subscriptions().Get(context.Background()) if err != nil { t.Error(err) } for _, s := range resp { - if err := list.Subscriptions().GetByID(s.ID).Delete(); err != nil { + if err := list.Subscriptions().GetByID(s.ID).Delete(context.Background()); err != nil { t.Error(err) } } - if resp, err := list.Subscriptions().Get(); err != nil || len(resp) != 0 { + if resp, err := list.Subscriptions().Get(context.Background()); err != nil || len(resp) != 0 { t.Error("can't delete subscription(s)") } }) diff --git a/api/user.go b/api/user.go index 51b7fe6..4128fc1 100644 --- a/api/user.go +++ b/api/user.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "github.com/koltyakov/gosip" @@ -48,17 +49,17 @@ func (user *User) ToURL() string { } // Get gets this user data object -func (user *User) Get() (UserResp, error) { +func (user *User) Get(ctx context.Context) (UserResp, error) { client := NewHTTPClient(user.client) - return client.Get(user.ToURL(), user.config) + return client.Get(ctx, user.ToURL(), user.config) } // Update updates User's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.User object -func (user *User) Update(body []byte) (UserResp, error) { +func (user *User) Update(ctx context.Context, body []byte) (UserResp, error) { body = patchMetadataType(body, "SP.User") client := NewHTTPClient(user.client) - return client.Update(user.endpoint, bytes.NewBuffer(body), user.config) + return client.Update(ctx, user.endpoint, bytes.NewBuffer(body), user.config) } // Groups gets Groups API instance queryable collection for this User diff --git a/api/user_test.go b/api/user_test.go index 5666957..2f9e215 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" ) @@ -14,7 +15,7 @@ func TestUser(t *testing.T) { t.Run("Constructor", func(t *testing.T) { u := NewUser(spClient, endpoint, nil) - if _, err := u.Select("Id").Get(); err != nil { + if _, err := u.Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) @@ -30,7 +31,7 @@ func TestUser(t *testing.T) { }) t.Run("GetUserInfo", func(t *testing.T) { - data, err := user.Get() + data, err := user.Get(context.Background()) if err != nil { t.Error(err) } @@ -45,7 +46,7 @@ func TestUser(t *testing.T) { }) t.Run("GetGroups", func(t *testing.T) { - if _, err := user.Groups().Select("Id").Get(); err != nil { + if _, err := user.Groups().Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/users.go b/api/users.go index abe91f8..909c7df 100644 --- a/api/users.go +++ b/api/users.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "net/url" @@ -37,9 +38,9 @@ func (users *Users) ToURL() string { } // Get gets Users queryable collection -func (users *Users) Get() (UsersResp, error) { +func (users *Users) Get(ctx context.Context) (UsersResp, error) { client := NewHTTPClient(users.client) - return client.Get(users.ToURL(), users.config) + return client.Get(ctx, users.ToURL(), users.config) } // GetByID gets a user by his/her ID (numeric ID from User Information List) diff --git a/api/users_test.go b/api/users_test.go index 3e465e9..9f56a47 100644 --- a/api/users_test.go +++ b/api/users_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" ) @@ -15,7 +16,7 @@ func TestUsers(t *testing.T) { t.Run("Constructor", func(t *testing.T) { u := NewUsers(spClient, endpoint, nil) - if _, err := u.Select("Id").Get(); err != nil { + if _, err := u.Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) @@ -31,7 +32,7 @@ func TestUsers(t *testing.T) { }) t.Run("GetUsers", func(t *testing.T) { - data, err := users.Select("Id").Top(5).Get() + data, err := users.Select("Id").Top(5).Get(context.Background()) if err != nil { t.Error(err) } @@ -46,7 +47,7 @@ func TestUsers(t *testing.T) { }) t.Run("GetUser", func(t *testing.T) { - data, err := NewSP(spClient).Web().CurrentUser().Get() + data, err := NewSP(spClient).Web().CurrentUser().Get(context.Background()) if err != nil { t.Error(err) } @@ -58,7 +59,7 @@ func TestUsers(t *testing.T) { t.Skip("no user ID to use in the test") } - data, err := users.GetByID(user.ID).Select("Id").Get() + data, err := users.GetByID(user.ID).Select("Id").Get(context.Background()) if err != nil { t.Error(err) } @@ -80,7 +81,7 @@ func TestUsers(t *testing.T) { t.Skip("no user LoginName to use in the test") } - data, err := users.GetByLoginName(user.LoginName).Select("LoginName").Get() + data, err := users.GetByLoginName(user.LoginName).Select("LoginName").Get(context.Background()) if err != nil { t.Error(err) } @@ -99,7 +100,7 @@ func TestUsers(t *testing.T) { t.Skip("no user Email to use in the test") } - data, err := users.GetByEmail(user.Email).Select("Email").Get() + data, err := users.GetByEmail(user.Email).Select("Email").Get(context.Background()) if err != nil { t.Error(err) } diff --git a/api/utility.go b/api/utility.go index 0f09278..87c4342 100644 --- a/api/utility.go +++ b/api/utility.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -36,7 +37,7 @@ func NewUtility(client *gosip.SPClient, endpoint string, config *RequestConfig) } // SendEmail sends an email via REST API due to the provided EmailProps options -func (utility *Utility) SendEmail(options *EmailProps) error { +func (utility *Utility) SendEmail(ctx context.Context, options *EmailProps) error { endpoint := fmt.Sprintf( "%s/_api/SP.Utilities.Utility.SendEmail", getPriorEndpoint(utility.endpoint, "/_api"), @@ -63,6 +64,6 @@ func (utility *Utility) SendEmail(options *EmailProps) error { JSONProps := string(props) body := []byte(TrimMultiline(`{ "properties": ` + JSONProps + `}`)) - _, err := client.Post(endpoint, bytes.NewBuffer(body), utility.config) + _, err := client.Post(ctx, endpoint, bytes.NewBuffer(body), utility.config) return err } diff --git a/api/utility_test.go b/api/utility_test.go index 7397727..dffe51c 100644 --- a/api/utility_test.go +++ b/api/utility_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "testing" ) @@ -13,12 +14,12 @@ func TestUtility(t *testing.T) { if spClient.AuthCnfg.GetStrategy() == "addin" { t.Skip("not supported by addin auth") } - user, err := sp.Web().CurrentUser().Get() + user, err := sp.Web().CurrentUser().Get(context.Background()) if err != nil { t.Error(err) } if user.Data().Email != "" { - if err := sp.Utility().SendEmail(&EmailProps{ + if err := sp.Utility().SendEmail(context.Background(), &EmailProps{ Subject: "Gosip SendEmail utility test", Body: "Feel free to delete the email", To: []string{user.Data().Email}, @@ -32,12 +33,12 @@ func TestUtility(t *testing.T) { if spClient.AuthCnfg.GetStrategy() == "addin" { t.Skip("not supported by addin auth") } - user, err := sp.Web().CurrentUser().Get() + user, err := sp.Web().CurrentUser().Get(context.Background()) if err != nil { t.Error(err) } if user.Data().Email != "" { - if err := sp.Utility().SendEmail(&EmailProps{ + if err := sp.Utility().SendEmail(context.Background(), &EmailProps{ Subject: "Gosip SendEmail utility test", Body: "Feel free to delete the email", To: []string{user.Data().Email}, diff --git a/api/view.go b/api/view.go index e201339..8ff70be 100644 --- a/api/view.go +++ b/api/view.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -69,28 +70,28 @@ func (view *View) ToURL() string { } // Get gets this View data response -func (view *View) Get() (ViewResp, error) { +func (view *View) Get(ctx context.Context) (ViewResp, error) { client := NewHTTPClient(view.client) - return client.Get(view.ToURL(), view.config) + return client.Get(ctx, view.ToURL(), view.config) } // Update updates View's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.View object -func (view *View) Update(body []byte) (ViewResp, error) { +func (view *View) Update(ctx context.Context, body []byte) (ViewResp, error) { body = patchMetadataType(body, "SP.View") client := NewHTTPClient(view.client) - return client.Update(view.endpoint, bytes.NewBuffer(body), view.config) + return client.Update(ctx, view.endpoint, bytes.NewBuffer(body), view.config) } // Delete deletes this View (can't be restored from a recycle bin) -func (view *View) Delete() error { +func (view *View) Delete(ctx context.Context) error { client := NewHTTPClient(view.client) - _, err := client.Delete(view.endpoint, view.config) + _, err := client.Delete(ctx, view.endpoint, view.config) return err } // SetViewXML updates view XML -func (view *View) SetViewXML(viewXML string) (ViewResp, error) { +func (view *View) SetViewXML(ctx context.Context, viewXML string) (ViewResp, error) { endpoint := fmt.Sprintf("%s/SetViewXml()", view.endpoint) payload, err := json.Marshal(&struct { ViewXML string `json:"viewXml"` @@ -101,5 +102,5 @@ func (view *View) SetViewXML(viewXML string) (ViewResp, error) { return nil, err } client := NewHTTPClient(view.client) - return client.Post(endpoint, bytes.NewBuffer(payload), view.config) + return client.Post(ctx, endpoint, bytes.NewBuffer(payload), view.config) } diff --git a/api/view_test.go b/api/view_test.go index fe14345..2b05896 100644 --- a/api/view_test.go +++ b/api/view_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "testing" @@ -15,7 +16,7 @@ func TestView(t *testing.T) { listURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" t.Run("Get", func(t *testing.T) { - data, err := web.GetList(listURI).Views().DefaultView().Get() + data, err := web.GetList(listURI).Views().DefaultView().Get(context.Background()) if err != nil { t.Error(err) } @@ -34,15 +35,15 @@ func TestView(t *testing.T) { "PersonalView": true, } data, _ := json.Marshal(meta) - vr, err := web.GetList(listURI).Views().Add(data) + vr, err := web.GetList(listURI).Views().Add(context.Background(), data) if err != nil { t.Error(err) } if _, err := web.GetList(listURI).Views().GetByID(vr.Data().ID). - SetViewXML(vr.Data().ListViewXML); err != nil { + SetViewXML(context.Background(), vr.Data().ListViewXML); err != nil { t.Error(err) } - if err := web.GetList(listURI).Views().GetByID(vr.Data().ID).Delete(); err != nil { + if err := web.GetList(listURI).Views().GetByID(vr.Data().ID).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -54,15 +55,15 @@ func TestView(t *testing.T) { "PersonalView": true, } data, _ := json.Marshal(meta) - vr, err := web.GetList(listURI).Views().Add(data) + vr, err := web.GetList(listURI).Views().Add(context.Background(), data) if err != nil { t.Error(err) } if _, err := web.GetList(listURI).Views().GetByID(vr.Data().ID). - Update([]byte(`{"PersonalView":false}`)); err != nil { + Update(context.Background(), []byte(`{"PersonalView":false}`)); err != nil { t.Error(err) } - if err := web.GetList(listURI).Views().GetByID(vr.Data().ID).Delete(); err != nil { + if err := web.GetList(listURI).Views().GetByID(vr.Data().ID).Delete(context.Background()); err != nil { t.Error(err) } }) diff --git a/api/views.go b/api/views.go index 21b5fca..83ac062 100644 --- a/api/views.go +++ b/api/views.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "fmt" "github.com/koltyakov/gosip" @@ -37,17 +38,17 @@ func (views *Views) ToURL() string { } // Get gets this List or Document Library views collection -func (views *Views) Get() (ViewsResp, error) { +func (views *Views) Get(ctx context.Context) (ViewsResp, error) { client := NewHTTPClient(views.client) - return client.Get(views.ToURL(), views.config) + return client.Get(ctx, views.ToURL(), views.config) } // Add adds view with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.View object -func (views *Views) Add(body []byte) (ViewResp, error) { +func (views *Views) Add(ctx context.Context, body []byte) (ViewResp, error) { body = patchMetadataType(body, "SP.View") client := NewHTTPClient(views.client) - return client.Post(views.endpoint, bytes.NewBuffer(body), views.config) + return client.Post(ctx, views.endpoint, bytes.NewBuffer(body), views.config) } // GetByID gets a view by its ID (GUID) diff --git a/api/views_test.go b/api/views_test.go index d9bc859..6f83ff2 100644 --- a/api/views_test.go +++ b/api/views_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "testing" ) @@ -16,7 +17,7 @@ func TestViews(t *testing.T) { } t.Run("Get", func(t *testing.T) { - data, err := web.GetList(listURI).Views().Get() + data, err := web.GetList(listURI).Views().Get(context.Background()) if err != nil { t.Error(err) } @@ -29,19 +30,19 @@ func TestViews(t *testing.T) { }) t.Run("GetByID", func(t *testing.T) { - if _, err := web.GetList(listURI).Views().GetByID(view.ID).Get(); err != nil { + if _, err := web.GetList(listURI).Views().GetByID(view.ID).Get(context.Background()); err != nil { t.Error(err) } }) t.Run("DefaultView", func(t *testing.T) { - if _, err := web.GetList(listURI).Views().DefaultView().Get(); err != nil { + if _, err := web.GetList(listURI).Views().DefaultView().Get(context.Background()); err != nil { t.Error(err) } }) t.Run("GetByTitle", func(t *testing.T) { - if _, err := web.GetList(listURI).Views().GetByTitle(view.Title).Get(); err != nil { + if _, err := web.GetList(listURI).Views().GetByTitle(view.Title).Get(context.Background()); err != nil { t.Error(err) } }) @@ -54,7 +55,7 @@ func TestViews(t *testing.T) { func getAnyView() (*ViewInfo, error) { web := NewSP(spClient).Web() listURI := getRelativeURL(spClient.AuthCnfg.GetSiteURL()) + "/Shared%20Documents" - data, err := web.GetList(listURI).Views().Top(1).Get() + data, err := web.GetList(listURI).Views().Top(1).Get(context.Background()) if err != nil { return nil, err } diff --git a/api/web.go b/api/web.go index da09d43..fa0b8b9 100644 --- a/api/web.go +++ b/api/web.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" "strings" @@ -94,24 +95,24 @@ func (web *Web) FromURL(url string) *Web { } // Get gets this Web info -func (web *Web) Get() (WebResp, error) { +func (web *Web) Get(ctx context.Context) (WebResp, error) { client := NewHTTPClient(web.client) - return client.Get(web.ToURL(), web.config) + return client.Get(ctx, web.ToURL(), web.config) } // Delete deletes this Web -func (web *Web) Delete() error { +func (web *Web) Delete(ctx context.Context) error { client := NewHTTPClient(web.client) - _, err := client.Delete(web.endpoint, web.config) + _, err := client.Delete(ctx, web.endpoint, web.config) return err } // Update updates Web's metadata with properties provided in `body` parameter // where `body` is byte array representation of JSON string payload relevant to SP.Web object -func (web *Web) Update(body []byte) (WebResp, error) { +func (web *Web) Update(ctx context.Context, body []byte) (WebResp, error) { body = patchMetadataType(body, "SP.Web") client := NewHTTPClient(web.client) - return client.Update(web.endpoint, bytes.NewBuffer(body), web.config) + return client.Update(ctx, web.endpoint, bytes.NewBuffer(body), web.config) } // Lists gets Lists API instance object @@ -198,7 +199,7 @@ func (web *Web) GetList(listURI string) *List { } // EnsureUser ensures a user by a `loginName` parameter and returns UserInfo -func (web *Web) EnsureUser(loginName string) (*UserInfo, error) { +func (web *Web) EnsureUser(ctx context.Context, loginName string) (*UserInfo, error) { client := NewHTTPClient(web.client) endpoint := fmt.Sprintf("%s/EnsureUser", web.endpoint) @@ -207,7 +208,7 @@ func (web *Web) EnsureUser(loginName string) (*UserInfo, error) { body := fmt.Sprintf(`{"logonName": "%s"}`, loginName) - data, err := client.Post(endpoint, bytes.NewBuffer([]byte(body)), patchConfigHeaders(web.config, headers)) + data, err := client.Post(ctx, endpoint, bytes.NewBuffer([]byte(body)), patchConfigHeaders(web.config, headers)) if err != nil { return nil, err } @@ -310,13 +311,13 @@ func (web *Web) GetFolderByID(uniqueID string) *Folder { } // EnsureFolder is a helper to ensure a folder by its relevant URI, when there was no folder it's created -func (web *Web) EnsureFolder(serverRelativeURL string) ([]byte, error) { - return ensureFolder(web, serverRelativeURL, serverRelativeURL, "legacy") +func (web *Web) EnsureFolder(ctx context.Context, serverRelativeURL string) ([]byte, error) { + return ensureFolder(ctx, web, serverRelativeURL, serverRelativeURL, "legacy") } // EnsureFolderByPath is a helper to ensure a folder by its relevant URI, when there was no folder it's created -func (web *Web) EnsureFolderByPath(serverRelativeURL string) ([]byte, error) { - return ensureFolder(web, serverRelativeURL, serverRelativeURL, "modern") +func (web *Web) EnsureFolderByPath(ctx context.Context, serverRelativeURL string) ([]byte, error) { + return ensureFolder(ctx, web, serverRelativeURL, serverRelativeURL, "modern") } // GetFile gets File API instance object by its relevant URI @@ -407,6 +408,6 @@ func (web *Web) RecycleBin() *RecycleBin { } // ContextInfo gets Context info object for this Web -func (web *Web) ContextInfo() (*ContextInfo, error) { - return NewContext(web.client, web.ToURL(), web.config).Get() +func (web *Web) ContextInfo(ctx context.Context) (*ContextInfo, error) { + return NewContext(web.client, web.ToURL(), web.config).Get(ctx) } diff --git a/api/web_test.go b/api/web_test.go index 53d88c5..0efeb0d 100644 --- a/api/web_test.go +++ b/api/web_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "net/url" "testing" @@ -17,7 +18,7 @@ func TestWeb(t *testing.T) { t.Run("Constructor", func(t *testing.T) { w := NewWeb(spClient, endpoint, nil) - if _, err := w.Select("Id").Get(); err != nil { + if _, err := w.Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) @@ -59,7 +60,7 @@ func TestWeb(t *testing.T) { }) t.Run("GetTitle", func(t *testing.T) { - data, err := web.Select("Title").Conf(headers.verbose).Get() + data, err := web.Select("Title").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -74,7 +75,7 @@ func TestWeb(t *testing.T) { }) t.Run("NoTitle", func(t *testing.T) { - data, err := web.Select("Id").Conf(headers.verbose).Get() + data, err := web.Select("Id").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -89,7 +90,7 @@ func TestWeb(t *testing.T) { t.Skip("is not applicable for Addin Only auth strategy") } - data, err := web.CurrentUser().Select("LoginName").Conf(headers.verbose).Get() + data, err := web.CurrentUser().Select("LoginName").Conf(headers.verbose).Get(context.Background()) if err != nil { t.Error(err) } @@ -101,10 +102,10 @@ func TestWeb(t *testing.T) { t.Run("EnsureFolder", func(t *testing.T) { guid := uuid.New().String() - if _, err := web.EnsureFolder("Shared Documents/" + guid + "/doc1/doc2/doc3/doc4"); err != nil { + if _, err := web.EnsureFolder(context.Background(), "Shared Documents/"+guid+"/doc1/doc2/doc3/doc4"); err != nil { t.Error(err) } - if err := web.GetFolder("Shared Documents/" + guid).Delete(); err != nil { + if err := web.GetFolder("Shared Documents/" + guid).Delete(context.Background()); err != nil { t.Error(err) } }) @@ -115,38 +116,38 @@ func TestWeb(t *testing.T) { } guid := uuid.New().String() - if _, err := web.EnsureFolderByPath("Shared Documents/" + guid + "/doc1/with #/special %"); err != nil { + if _, err := web.EnsureFolderByPath(context.Background(), "Shared Documents/"+guid+"/doc1/with #/special %"); err != nil { t.Error(err) } - if err := web.GetFolder("Shared Documents/" + guid).Delete(); err != nil { + if err := web.GetFolder("Shared Documents/" + guid).Delete(context.Background()); err != nil { t.Error(err) } }) t.Run("EnsureUser", func(t *testing.T) { - user, err := sp.Web().CurrentUser().Get() + user, err := sp.Web().CurrentUser().Get(context.Background()) if err != nil { t.Error(err) } - if _, err := sp.Web().EnsureUser(user.Data().Email); err != nil { + if _, err := sp.Web().EnsureUser(context.Background(), user.Data().Email); err != nil { t.Error(err) } }) t.Run("UserInfoList", func(t *testing.T) { - if _, err := sp.Web().UserInfoList().Select("Id").Get(); err != nil { + if _, err := sp.Web().UserInfoList().Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) t.Run("Roles", func(t *testing.T) { - if _, err := sp.Web().Roles().HasUniqueAssignments(); err != nil { + if _, err := sp.Web().Roles().HasUniqueAssignments(context.Background()); err != nil { t.Error(err) } }) t.Run("AvailableContentTypes", func(t *testing.T) { - resp, err := sp.Web().AvailableContentTypes().Get() + resp, err := sp.Web().AvailableContentTypes().Get(context.Background()) if err != nil { t.Error(err) } diff --git a/api/webs.go b/api/webs.go index 15d59bf..c4ba821 100644 --- a/api/webs.go +++ b/api/webs.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "encoding/json" "fmt" @@ -38,16 +39,16 @@ func (webs *Webs) ToURL() string { } // Get gets Webs response - a collection of WebInfo for the parent Web -func (webs *Webs) Get() (WebsResp, error) { +func (webs *Webs) Get(ctx context.Context) (WebsResp, error) { client := NewHTTPClient(webs.client) - return client.Get(webs.ToURL(), webs.config) + return client.Get(ctx, webs.ToURL(), webs.config) } // Add creates a sub web for a parent web with provided `title` and `url`. // `url` stands for a system friendly URI (e.g. `finances`) while `title` is a human friendly name (e.g. `Financial Department`). // Along with title and url additional metadata can be provided in optional `metadata` string map object. // `metadata` props should correspond to `SP.WebCreationInformation` API type. Some props have defaults as Language (1033), WebTemplate (STS), etc. -func (webs *Webs) Add(title string, url string, metadata map[string]interface{}) (WebResp, error) { +func (webs *Webs) Add(ctx context.Context, title string, url string, metadata map[string]interface{}) (WebResp, error) { endpoint := fmt.Sprintf("%s/Add", webs.endpoint) if metadata == nil { @@ -86,5 +87,5 @@ func (webs *Webs) Add(title string, url string, metadata map[string]interface{}) headers["Accept"] = "application/json;odata=verbose" headers["Content-Type"] = "application/json;odata=verbose;charset=utf-8" - return client.Post(endpoint, bytes.NewBuffer([]byte(body)), patchConfigHeaders(webs.config, headers)) + return client.Post(ctx, endpoint, bytes.NewBuffer([]byte(body)), patchConfigHeaders(webs.config, headers)) } diff --git a/api/webs_test.go b/api/webs_test.go index c941fa8..82221b7 100644 --- a/api/webs_test.go +++ b/api/webs_test.go @@ -2,6 +2,7 @@ package api import ( "bytes" + "context" "strings" "testing" @@ -18,7 +19,7 @@ func TestWebs(t *testing.T) { t.Run("Constructor", func(t *testing.T) { w := NewWebs(spClient, endpoint, nil) - if _, err := w.Select("Id").Get(); err != nil { + if _, err := w.Select("Id").Get(context.Background()); err != nil { t.Error(err) } }) @@ -37,10 +38,10 @@ func TestWebs(t *testing.T) { if !heavyTests { t.Skip("setup SPAPI_HEAVY_TESTS env var to \"true\" to run this test") } - if _, err := webs.Add("CI: "+newWebGUID, "ci_"+newWebGUID, nil); err != nil { + if _, err := webs.Add(context.Background(), "CI: "+newWebGUID, "ci_"+newWebGUID, nil); err != nil { t.Error(err) } - data, err := webs.Select("Id,Title").Get() + data, err := webs.Select("Id,Title").Get(context.Background()) if err != nil { t.Error(err) } @@ -50,7 +51,7 @@ func TestWebs(t *testing.T) { }) t.Run("GetWebs", func(t *testing.T) { - data, err := webs.Select("Id,Title").Get() + data, err := webs.Select("Id,Title").Get(context.Background()) if err != nil { t.Error(err) } @@ -66,7 +67,7 @@ func TestWebs(t *testing.T) { } createdWebURL := spClient.AuthCnfg.GetSiteURL() + "/ci_" + newWebGUID subWeb := NewWeb(spClient, createdWebURL, nil) - if err := subWeb.Delete(); err != nil { + if err := subWeb.Delete(context.Background()); err != nil { t.Error(err) } }) @@ -74,10 +75,10 @@ func TestWebs(t *testing.T) { t.Run("CreateFieldAsXML", func(t *testing.T) { title := strings.Replace(uuid.New().String(), "-", "", -1) schemaXML := `` - if _, err := sp.Web().Fields().CreateFieldAsXML(schemaXML, 0); err != nil { + if _, err := sp.Web().Fields().CreateFieldAsXML(context.Background(), schemaXML, 0); err != nil { t.Error(err) } - if err := sp.Web().Fields().GetByInternalNameOrTitle(title).Delete(); err != nil { + if err := sp.Web().Fields().GetByInternalNameOrTitle(title).Delete(context.Background()); err != nil { t.Error(err) } }) diff --git a/auth/addin/auth.go b/auth/addin/auth.go index acb3cb2..c20b453 100644 --- a/auth/addin/auth.go +++ b/auth/addin/auth.go @@ -9,6 +9,7 @@ Amongst supported platform versions are: package addin import ( + "context" "encoding/json" "io" "net/http" @@ -84,7 +85,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return GetAuth(c) } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return GetAuth(ctx, c) } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } @@ -98,7 +99,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error if c.client == nil { c.client = &httpClient.Client } - authToken, _, err := c.GetAuth() + authToken, _, err := c.GetAuth(req.Context()) if err != nil { return err } diff --git a/auth/addin/helpers.go b/auth/addin/helpers.go index 76f932d..76b04d1 100644 --- a/auth/addin/helpers.go +++ b/auth/addin/helpers.go @@ -1,6 +1,7 @@ package addin import ( + "context" "encoding/json" "errors" "fmt" @@ -25,7 +26,7 @@ var ( ) // GetAuth gets authentication -func GetAuth(c *AuthCnfg) (string, int64, error) { +func GetAuth(ctx context.Context, c *AuthCnfg) (string, int64, error) { if c.client == nil { c.client = &http.Client{} } @@ -40,13 +41,13 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return accessToken.(string), exp.Unix(), nil } - realm, err := getRealm(c) + realm, err := getRealm(ctx, c) if err != nil { return "", 0, err } c.Realm = realm - authURL, err := getAuthURL(c, c.Realm) + authURL, err := getAuthURL(ctx, c, c.Realm) if err != nil { return "", 0, err } @@ -62,7 +63,12 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { params.Set("resource", resource) // resp, err := http.Post(authURL, "application/x-www-form-urlencoded", strings.NewReader(params.Encode())) - resp, err := c.client.Post(authURL, "application/x-www-form-urlencoded", strings.NewReader(params.Encode())) + req, err := http.NewRequestWithContext(ctx, "POST", authURL, strings.NewReader(params.Encode())) + if err != nil { + return "", 0, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err := c.client.Do(req) if err != nil { return "", 0, err } @@ -106,7 +112,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return results.AccessToken, exp, nil } -func getAuthURL(c *AuthCnfg, realm string) (string, error) { +func getAuthURL(ctx context.Context, c *AuthCnfg, realm string) (string, error) { if c.client == nil { c.client = &http.Client{} } @@ -119,7 +125,7 @@ func getAuthURL(c *AuthCnfg, realm string) (string, error) { return authURL.(string), nil } - req, err := http.NewRequest("GET", endpoint, nil) + req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil) if err != nil { return "", err } @@ -164,7 +170,7 @@ func getAuthURL(c *AuthCnfg, realm string) (string, error) { return "", errors.New("no OAuth2 protocol location found") } -func getRealm(c *AuthCnfg) (string, error) { +func getRealm(ctx context.Context, c *AuthCnfg) (string, error) { if c.client == nil { c.client = &http.Client{} } @@ -184,7 +190,7 @@ func getRealm(c *AuthCnfg) (string, error) { } endpoint := c.SiteURL + "/_vti_bin/client.svc" - req, err := http.NewRequest("POST", endpoint, nil) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, nil) if err != nil { return "", err } diff --git a/auth/addin/helpers_test.go b/auth/addin/helpers_test.go index 2628dad..5123c95 100644 --- a/auth/addin/helpers_test.go +++ b/auth/addin/helpers_test.go @@ -1,6 +1,7 @@ package addin import ( + "context" "testing" ) @@ -8,35 +9,35 @@ func TestHelpersEdgeCases(t *testing.T) { t.Run("GetAuth/EmptySiteURL", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty SiteURL should not go") } }) t.Run("GetAuth/IncorrectSiteURL", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: "https://wrong"} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("incorrect SiteURL should not go") } }) t.Run("getRealm/EmptyRealm", func(t *testing.T) { cnfg := &AuthCnfg{Realm: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty Realm should not go") } }) t.Run("getRealm/EmptySiteURL", func(t *testing.T) { cnfg := &AuthCnfg{Realm: "any", SiteURL: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty SiteURL should not go") } }) t.Run("getRealm/IncorrectSiteURL", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: "https://wrong", Realm: "wrong"} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("incorrect SiteURL should not go") } }) diff --git a/auth/adfs/auth.go b/auth/adfs/auth.go index bf37cfc..73a7fab 100644 --- a/auth/adfs/auth.go +++ b/auth/adfs/auth.go @@ -8,6 +8,7 @@ Amongst supported platform versions are: package adfs import ( + "context" "encoding/json" "io" "net/http" @@ -117,7 +118,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return GetAuth(c) } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return GetAuth(ctx, c) } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } @@ -131,7 +132,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error if c.client == nil { c.client = &httpClient.Client } - authCookie, _, err := c.GetAuth() + authCookie, _, err := c.GetAuth(req.Context()) if err != nil { return err } diff --git a/auth/adfs/helpers.go b/auth/adfs/helpers.go index 518f0c7..f5410f7 100644 --- a/auth/adfs/helpers.go +++ b/auth/adfs/helpers.go @@ -2,6 +2,7 @@ package adfs import ( "bytes" + "context" "encoding/xml" "errors" "fmt" @@ -21,7 +22,7 @@ var ( ) // GetAuth gets authentication -func GetAuth(c *AuthCnfg) (string, int64, error) { +func GetAuth(ctx context.Context, c *AuthCnfg) (string, int64, error) { if c.client == nil { c.client = &http.Client{} } @@ -41,7 +42,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { // In case of WAP if c.AdfsCookie == "EdgeAccessCookie" { - authCookie, expires, err = wapAuthFlow(c) + authCookie, expires, err = wapAuthFlow(ctx, c) if err != nil { return "", 0, err } @@ -49,7 +50,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { expiry = 30 * time.Minute // ToDO: move to settings or dynamically get } } else { - authCookie, expires, err = adfsAuthFlow(c, "") + authCookie, expires, err = adfsAuthFlow(ctx, c, "") if err != nil { return "", 0, err } @@ -63,7 +64,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return authCookie, exp, nil } -func adfsAuthFlow(c *AuthCnfg, edgeCookie string) (string, string, error) { +func adfsAuthFlow(ctx context.Context, c *AuthCnfg, edgeCookie string) (string, string, error) { if c.client == nil { c.client = &http.Client{} } @@ -79,7 +80,7 @@ func adfsAuthFlow(c *AuthCnfg, edgeCookie string) (string, string, error) { return "", "", err } - req, err := http.NewRequest("POST", usernameMixedURL, bytes.NewBuffer([]byte(samlBody))) + req, err := http.NewRequestWithContext(ctx, "POST", usernameMixedURL, bytes.NewBuffer([]byte(samlBody))) if err != nil { return "", "", err } @@ -170,7 +171,7 @@ func adfsAuthFlow(c *AuthCnfg, edgeCookie string) (string, string, error) { // } c.client.CheckRedirect = doNotCheckRedirect - req, err = http.NewRequest("POST", rootSiteURL+"/_trust/", strings.NewReader(params.Encode())) + req, err = http.NewRequestWithContext(ctx, "POST", rootSiteURL+"/_trust/", strings.NewReader(params.Encode())) if err != nil { return "", "", err } @@ -201,7 +202,7 @@ func adfsAuthFlow(c *AuthCnfg, edgeCookie string) (string, string, error) { } // WAP auth flow - TODO: refactor -func wapAuthFlow(c *AuthCnfg) (string, string, error) { +func wapAuthFlow(ctx context.Context, c *AuthCnfg) (string, string, error) { if c.client == nil { c.client = &http.Client{} } @@ -213,8 +214,11 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { // }, // } c.client.CheckRedirect = doNotCheckRedirect - - resp, err := c.client.Get(c.SiteURL) + req, err := http.NewRequestWithContext(ctx, "GET", c.SiteURL, nil) + if err != nil { + return "", "", err + } + resp, err := c.client.Do(req) if err != nil { return "", "", err } @@ -241,7 +245,12 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { params.Set("Password", c.Password) params.Set("AuthMethod", "FormsAuthentication") - resp, err = c.client.Post(redirectURL, "application/x-www-form-urlencoded", strings.NewReader(params.Encode())) + redirectReq, err := http.NewRequestWithContext(ctx, "POST", redirectURL, strings.NewReader(params.Encode())) + if err != nil { + return "", "", err + } + redirectReq.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err = c.client.Do(redirectReq) if err != nil { return "", "", err } @@ -256,7 +265,7 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { } // Request to redirect URL using MSISAuth - req, err := http.NewRequest("GET", redirectURL, nil) + msisAuthReq, err := http.NewRequestWithContext(ctx, "GET", redirectURL, nil) if err != nil { return "", "", err } @@ -267,10 +276,10 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { return "", "", err } - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36") - req.Header.Set("Cookie", msisAuthCookie) + msisAuthReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36") + msisAuthReq.Header.Set("Cookie", msisAuthCookie) - resp, err = c.client.Do(req) + resp, err = c.client.Do(msisAuthReq) if err != nil { return "", "", err } @@ -291,7 +300,7 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { } redirectURL = redirect.String() - req, err = http.NewRequest("GET", redirectURL, nil) + req, err = http.NewRequestWithContext(ctx, "GET", redirectURL, nil) if err != nil { return "", "", err } @@ -325,7 +334,7 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { // client := &http.Client{} c.client.CheckRedirect = nil - req, err = http.NewRequest("GET", redirectURL, nil) + req, err = http.NewRequestWithContext(ctx, "GET", redirectURL, nil) if err != nil { return "", "", err } @@ -350,7 +359,7 @@ func wapAuthFlow(c *AuthCnfg) (string, string, error) { cc.RelyingParty = resp.Request.URL.Query().Get("wtrealm") cc.AdfsCookie = "FedAuth" - fedAuthCookie, expire, err := adfsAuthFlow(&cc, authCookie) + fedAuthCookie, expire, err := adfsAuthFlow(ctx, &cc, authCookie) if err != nil { return "", "", err } diff --git a/auth/adfs/helpers_test.go b/auth/adfs/helpers_test.go index 17947fa..3bb3e89 100644 --- a/auth/adfs/helpers_test.go +++ b/auth/adfs/helpers_test.go @@ -1,6 +1,7 @@ package adfs import ( + "context" "net/url" "testing" "time" @@ -10,14 +11,14 @@ func TestHelpersEdgeCases(t *testing.T) { t.Run("GetAuth/EmptySiteURL", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty SiteURL should not go") } }) t.Run("adfsAuthFlow/EmptyAdfsURL", func(t *testing.T) { cnfg := &AuthCnfg{AdfsURL: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty AdfsURL should not go") } }) diff --git a/auth/anon/anon.go b/auth/anon/anon.go index cdf1038..7d29a5a 100644 --- a/auth/anon/anon.go +++ b/auth/anon/anon.go @@ -3,6 +3,7 @@ package anon import ( + "context" "encoding/json" "io" "net/http" @@ -52,7 +53,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return "", 0, nil } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return "", 0, nil } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } diff --git a/auth/anon/anon_test.go b/auth/anon/anon_test.go index f7da651..fd957ef 100644 --- a/auth/anon/anon_test.go +++ b/auth/anon/anon_test.go @@ -1,6 +1,7 @@ package anon import ( + "context" "net/http" "os" "testing" @@ -76,7 +77,7 @@ func TestAuthEdgeCases(t *testing.T) { t.Run("GetAuth", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: "http://test"} - if _, _, err := cnfg.GetAuth(); err != nil { + if _, _, err := cnfg.GetAuth(context.Background()); err != nil { t.Error(err) } }) diff --git a/auth/azurecert/azurecert.go b/auth/azurecert/azurecert.go index 11a62db..8023148 100644 --- a/auth/azurecert/azurecert.go +++ b/auth/azurecert/azurecert.go @@ -7,6 +7,7 @@ package azurecert import ( + "context" "encoding/base64" "encoding/json" "fmt" @@ -99,7 +100,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { if c.authorizer == nil { u, _ := url.Parse(c.SiteURL) resource := fmt.Sprintf("https://%s", u.Host) @@ -120,7 +121,7 @@ func (c *AuthCnfg) GetAuth() (string, int64, error) { // } // return token.Token().AccessToken, token.Token().Expires().Unix(), nil - return c.getToken() + return c.getToken(ctx) } // GetSiteURL gets SharePoint siteURL @@ -132,7 +133,7 @@ func (c *AuthCnfg) GetStrategy() string { return "azurecert" } // SetAuth authenticates request // noinspection GoUnusedParameter func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error { - authToken, _, err := c.GetAuth() + authToken, _, err := c.GetAuth(req.Context()) if err != nil { return err } @@ -142,7 +143,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error } // Getting token with prepare for external usage scenarious -func (c *AuthCnfg) getToken() (string, int64, error) { +func (c *AuthCnfg) getToken(ctx context.Context) (string, int64, error) { // Get from cache parsedURL, err := url.Parse(c.SiteURL) if err != nil { @@ -154,7 +155,7 @@ func (c *AuthCnfg) getToken() (string, int64, error) { } // Get token - req, _ := http.NewRequest("GET", c.SiteURL, nil) + req, _ := http.NewRequestWithContext(ctx, "GET", c.SiteURL, nil) req, err = c.authorizer.WithAuthorization()(preparer{}).Prepare(req) if err != nil { return "", 0, err diff --git a/auth/azurecreds/azurecreds.go b/auth/azurecreds/azurecreds.go index f4dc0f8..91ba838 100644 --- a/auth/azurecreds/azurecreds.go +++ b/auth/azurecreds/azurecreds.go @@ -7,6 +7,7 @@ package azurecreds import ( + "context" "encoding/base64" "encoding/json" "fmt" @@ -96,7 +97,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { if c.authorizer == nil { u, _ := url.Parse(c.SiteURL) resource := fmt.Sprintf("https://%s", u.Host) @@ -117,7 +118,7 @@ func (c *AuthCnfg) GetAuth() (string, int64, error) { // } // return token.Token().AccessToken, token.Token().Expires().Unix(), nil - return c.getToken() + return c.getToken(ctx) } // GetSiteURL gets SharePoint siteURL @@ -129,7 +130,7 @@ func (c *AuthCnfg) GetStrategy() string { return "azurecreds" } // SetAuth authenticates request // noinspection GoUnusedParameter func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error { - authToken, _, err := c.GetAuth() + authToken, _, err := c.GetAuth(req.Context()) if err != nil { return err } @@ -139,7 +140,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error } // Getting token with prepare for external usage scenarious -func (c *AuthCnfg) getToken() (string, int64, error) { +func (c *AuthCnfg) getToken(ctx context.Context) (string, int64, error) { // Get from cache parsedURL, err := url.Parse(c.SiteURL) if err != nil { @@ -151,7 +152,7 @@ func (c *AuthCnfg) getToken() (string, int64, error) { } // Get token - req, _ := http.NewRequest("GET", c.SiteURL, nil) + req, _ := http.NewRequestWithContext(ctx, "GET", c.SiteURL, nil) req, err = c.authorizer.WithAuthorization()(preparer{}).Prepare(req) if err != nil { return "", 0, err diff --git a/auth/azureenv/azureenv.go b/auth/azureenv/azureenv.go index d55ff96..a10bb73 100644 --- a/auth/azureenv/azureenv.go +++ b/auth/azureenv/azureenv.go @@ -15,6 +15,7 @@ package azureenv import ( + "context" "encoding/base64" "encoding/json" "fmt" @@ -89,7 +90,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { if c.authorizer == nil { u, _ := url.Parse(c.SiteURL) resource := fmt.Sprintf("https://%s", u.Host) @@ -102,7 +103,7 @@ func (c *AuthCnfg) GetAuth() (string, int64, error) { c.authorizer = authorizer } - return c.getToken() + return c.getToken(ctx) } // GetSiteURL gets SharePoint siteURL @@ -114,7 +115,7 @@ func (c *AuthCnfg) GetStrategy() string { return "azureenv" } // SetAuth authenticates request // noinspection GoUnusedParameter func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error { - if _, _, err := c.GetAuth(); err != nil { + if _, _, err := c.GetAuth(req.Context()); err != nil { return err } _, err := c.authorizer.WithAuthorization()(preparer{}).Prepare(req) @@ -154,8 +155,8 @@ func (c *AuthCnfg) newAuthorizerWithEnvVars( } // Getting token with prepare for external usage scenarious -func (c *AuthCnfg) getToken() (string, int64, error) { - req, _ := http.NewRequest("GET", c.SiteURL, nil) +func (c *AuthCnfg) getToken(ctx context.Context) (string, int64, error) { + req, _ := http.NewRequestWithContext(ctx, "GET", c.SiteURL, nil) req, err := c.authorizer.WithAuthorization()(preparer{}).Prepare(req) if err != nil { return "", 0, err diff --git a/auth/device/device.go b/auth/device/device.go index 605b3d4..29d38c6 100644 --- a/auth/device/device.go +++ b/auth/device/device.go @@ -5,6 +5,7 @@ package device import ( + "context" "encoding/json" "fmt" "io" @@ -66,7 +67,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { u, _ := url.Parse(c.SiteURL) resource := fmt.Sprintf("https://%s", u.Host) @@ -96,7 +97,7 @@ func (c *AuthCnfg) GetAuth() (string, int64, error) { config := auth.NewDeviceFlowConfig(c.ClientID, c.TenantID) config.Resource = resource - token, err := config.ServicePrincipalToken() + token, err := config.ServicePrincipalToken(ctx) if err != nil { return "", 0, err } @@ -116,7 +117,7 @@ func (c *AuthCnfg) GetStrategy() string { return "device" } // SetAuth authenticates request // noinspection GoUnusedParameter func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error { - accessToken, _, err := c.GetAuth() + accessToken, _, err := c.GetAuth(req.Context()) if err != nil { return err } diff --git a/auth/fba/auth.go b/auth/fba/auth.go index dfb3745..172bd8b 100644 --- a/auth/fba/auth.go +++ b/auth/fba/auth.go @@ -7,6 +7,7 @@ Amongst supported platform versions are: package fba import ( + "context" "encoding/json" "io" "net/http" @@ -80,7 +81,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return GetAuth(c) } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return GetAuth(ctx, c) } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } @@ -94,7 +95,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error if c.client == nil { c.client = &httpClient.Client } - authCookie, _, err := c.GetAuth() + authCookie, _, err := c.GetAuth(req.Context()) if err != nil { return err } diff --git a/auth/fba/helpers.go b/auth/fba/helpers.go index d72d4eb..a949e9e 100644 --- a/auth/fba/helpers.go +++ b/auth/fba/helpers.go @@ -2,6 +2,7 @@ package fba import ( "bytes" + "context" "encoding/xml" "errors" "fmt" @@ -20,7 +21,7 @@ var ( ) // GetAuth gets authentication -func GetAuth(c *AuthCnfg) (string, int64, error) { +func GetAuth(ctx context.Context, c *AuthCnfg) (string, int64, error) { if c.client == nil { c.client = &http.Client{} } @@ -41,7 +42,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return "", 0, err } - req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer([]byte(soapBody))) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, bytes.NewBuffer([]byte(soapBody))) if err != nil { return "", 0, err } diff --git a/auth/ntlm/auth.go b/auth/ntlm/auth.go index ca8a807..9d7796b 100644 --- a/auth/ntlm/auth.go +++ b/auth/ntlm/auth.go @@ -9,6 +9,7 @@ Amongst supported platform versions are: package ntlm import ( + "context" "encoding/json" "io" "net/http" @@ -100,7 +101,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return "", 0, nil } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return "", 0, nil } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } diff --git a/auth/ntlm/auth_test.go b/auth/ntlm/auth_test.go index 337313a..46a0ac1 100644 --- a/auth/ntlm/auth_test.go +++ b/auth/ntlm/auth_test.go @@ -1,6 +1,7 @@ package ntlm import ( + "context" "os" "testing" @@ -103,7 +104,7 @@ func TestAuthEdgeCases(t *testing.T) { t.Run("GetAuth", func(t *testing.T) { cnfg := &AuthCnfg{} - r, _, err := cnfg.GetAuth() + r, _, err := cnfg.GetAuth(context.Background()) if err != nil { t.Error(err) } diff --git a/auth/saml/auth.go b/auth/saml/auth.go index eed0c82..5ab981a 100644 --- a/auth/saml/auth.go +++ b/auth/saml/auth.go @@ -9,6 +9,7 @@ Amongst supported platform versions are: package saml import ( + "context" "encoding/json" "io" "net/http" @@ -82,7 +83,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return GetAuth(c) } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return GetAuth(ctx, c) } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } @@ -96,7 +97,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error if c.client == nil { c.client = &httpClient.Client } - authCookie, _, err := c.GetAuth() + authCookie, _, err := c.GetAuth(req.Context()) if err != nil { return err } diff --git a/auth/saml/helpers.go b/auth/saml/helpers.go index e841d35..d786fdb 100644 --- a/auth/saml/helpers.go +++ b/auth/saml/helpers.go @@ -2,6 +2,7 @@ package saml import ( "bytes" + "context" "encoding/json" "encoding/xml" "errors" @@ -29,7 +30,7 @@ var ( ) // GetAuth gets authentication -func GetAuth(c *AuthCnfg) (string, int64, error) { +func GetAuth(ctx context.Context, c *AuthCnfg) (string, int64, error) { if c.client == nil { c.client = &http.Client{} } @@ -44,7 +45,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return authToken.(string), exp.Unix(), nil } - authCookie, notAfter, err := getSecurityToken(c) + authCookie, notAfter, err := getSecurityToken(ctx, c) if err != nil { return "", 0, err } @@ -58,7 +59,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return authCookie, exp, nil } -func getSecurityToken(c *AuthCnfg) (string, string, error) { +func getSecurityToken(ctx context.Context, c *AuthCnfg) (string, string, error) { if c.client == nil { c.client = &http.Client{} } @@ -76,7 +77,12 @@ func getSecurityToken(c *AuthCnfg) (string, string, error) { // } c.client.CheckRedirect = doNotCheckRedirect - resp, err := c.client.Post(endpoint, "application/x-www-form-urlencoded", strings.NewReader(params.Encode())) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, strings.NewReader(params.Encode())) + if err != nil { + return "", "", err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err := c.client.Do(req) if err != nil { return "", "", err } @@ -114,17 +120,17 @@ func getSecurityToken(c *AuthCnfg) (string, string, error) { } if userRealm.NameSpaceType == "Managed" { - return getSecurityTokenWithOnline(c) + return getSecurityTokenWithOnline(ctx, c) } if userRealm.NameSpaceType == "Federated" { - return getSecurityTokenWithAdfs(userRealm.AuthURL, c) + return getSecurityTokenWithAdfs(ctx, userRealm.AuthURL, c) } return "", "", fmt.Errorf("unable to resolve namespace authentiation type. Type received: %s", userRealm.NameSpaceType) } -func getSecurityTokenWithOnline(c *AuthCnfg) (string, string, error) { +func getSecurityTokenWithOnline(ctx context.Context, c *AuthCnfg) (string, string, error) { if c.client == nil { c.client = &http.Client{} } @@ -143,7 +149,7 @@ func getSecurityTokenWithOnline(c *AuthCnfg) (string, string, error) { loginEndpoint := loginEndpoints[resolveSPOEnv(c.SiteURL)] stsEndpoint := fmt.Sprintf("https://%s/extSTS.srf", loginEndpoint) - req, err := http.NewRequest("POST", stsEndpoint, bytes.NewBuffer([]byte(samlBody))) + req, err := http.NewRequestWithContext(ctx, "POST", stsEndpoint, bytes.NewBuffer([]byte(samlBody))) if err != nil { return "", "", err } @@ -218,7 +224,7 @@ func getSecurityTokenWithOnline(c *AuthCnfg) (string, string, error) { } // TODO: test the method, it possibly contains issues and extra complexity -func getSecurityTokenWithAdfs(adfsURL string, c *AuthCnfg) (string, string, error) { +func getSecurityTokenWithAdfs(ctx context.Context, adfsURL string, c *AuthCnfg) (string, string, error) { if c.client == nil { c.client = &http.Client{} } @@ -237,7 +243,7 @@ func getSecurityTokenWithAdfs(adfsURL string, c *AuthCnfg) (string, string, erro return "", "", err } - req, err := http.NewRequest("POST", usernameMixedURL, bytes.NewBuffer([]byte(samlBody))) + req, err := http.NewRequestWithContext(ctx, "POST", usernameMixedURL, bytes.NewBuffer([]byte(samlBody))) if err != nil { return "", "", err } @@ -303,7 +309,7 @@ func getSecurityTokenWithAdfs(adfsURL string, c *AuthCnfg) (string, string, erro stsEndpoint := "https://login.microsoftonline.com/extSTS.srf" // TODO: mapping - req, err = http.NewRequest("POST", stsEndpoint, bytes.NewBuffer([]byte(tokenRequest))) + req, err = http.NewRequestWithContext(ctx, "POST", stsEndpoint, bytes.NewBuffer([]byte(tokenRequest))) if err != nil { return "", "", err } diff --git a/auth/saml/helpers_test.go b/auth/saml/helpers_test.go index 8c144cc..703f743 100644 --- a/auth/saml/helpers_test.go +++ b/auth/saml/helpers_test.go @@ -1,6 +1,7 @@ package saml import ( + "context" "testing" ) @@ -8,17 +9,17 @@ func TestHelpersEdgeCases(t *testing.T) { t.Run("GetAuth/EmptySiteURL", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty SiteURL should not go") } }) t.Run("getSecurityTokenWithAdfs", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: ""} - if _, _, err := getSecurityTokenWithAdfs("wrong", cnfg); err == nil { + if _, _, err := getSecurityTokenWithAdfs(context.Background(), "wrong", cnfg); err == nil { t.Error("wrong adfsURL should not go") } - if _, _, err := getSecurityTokenWithAdfs("http://wrong", cnfg); err == nil { + if _, _, err := getSecurityTokenWithAdfs(context.Background(), "http://wrong", cnfg); err == nil { t.Error("wrong adfsURL should not go") } }) diff --git a/auth/tmg/auth.go b/auth/tmg/auth.go index 5222c26..836b6fc 100644 --- a/auth/tmg/auth.go +++ b/auth/tmg/auth.go @@ -9,6 +9,7 @@ Amongst supported platform versions are: package tmg import ( + "context" "encoding/json" "io" "net/http" @@ -82,7 +83,7 @@ func (c *AuthCnfg) WriteConfig(privateFile string) error { func (c *AuthCnfg) SetMasterkey(masterKey string) { c.masterKey = masterKey } // GetAuth authenticates, receives access token -func (c *AuthCnfg) GetAuth() (string, int64, error) { return GetAuth(c) } +func (c *AuthCnfg) GetAuth(ctx context.Context) (string, int64, error) { return GetAuth(ctx, c) } // GetSiteURL gets siteURL func (c *AuthCnfg) GetSiteURL() string { return c.SiteURL } @@ -96,7 +97,7 @@ func (c *AuthCnfg) SetAuth(req *http.Request, httpClient *gosip.SPClient) error if c.client == nil { c.client = &httpClient.Client } - authCookie, _, err := c.GetAuth() + authCookie, _, err := c.GetAuth(req.Context()) if err != nil { return err } diff --git a/auth/tmg/helpers.go b/auth/tmg/helpers.go index 5120855..f3ece93 100644 --- a/auth/tmg/helpers.go +++ b/auth/tmg/helpers.go @@ -1,6 +1,7 @@ package tmg import ( + "context" "fmt" "io" "net/http" @@ -16,7 +17,7 @@ var ( ) // GetAuth gets authentication -func GetAuth(c *AuthCnfg) (string, int64, error) { +func GetAuth(ctx context.Context, c *AuthCnfg) (string, int64, error) { if c.client == nil { c.client = &http.Client{} } @@ -31,7 +32,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return accessToken.(string), exp.Unix(), nil } - redirect, err := detectCookieAuthURL(c, c.SiteURL) + redirect, err := detectCookieAuthURL(ctx, c, c.SiteURL) if err != nil { return "", 0, err } @@ -59,8 +60,12 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { // }, // } c.client.CheckRedirect = doNotCheckRedirect - - resp, err := c.client.Post(endpoint, "application/x-www-form-urlencoded", strings.NewReader(params.Encode())) + req, err := http.NewRequestWithContext(ctx, "POST", endpoint, strings.NewReader(params.Encode())) + if err != nil { + return "", 0, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err := c.client.Do(req) if err != nil { return "", 0, err } @@ -85,7 +90,7 @@ func GetAuth(c *AuthCnfg) (string, int64, error) { return authCookie, exp, nil } -func detectCookieAuthURL(c *AuthCnfg, siteURL string) (*url.URL, error) { +func detectCookieAuthURL(ctx context.Context, c *AuthCnfg, siteURL string) (*url.URL, error) { if c.client == nil { c.client = &http.Client{} } @@ -97,7 +102,7 @@ func detectCookieAuthURL(c *AuthCnfg, siteURL string) (*url.URL, error) { // } c.client.CheckRedirect = doNotCheckRedirect - req, err := http.NewRequest("GET", siteURL, nil) + req, err := http.NewRequestWithContext(ctx, "GET", siteURL, nil) if err != nil { return nil, err } diff --git a/auth/tmg/helpers_test.go b/auth/tmg/helpers_test.go index aea0478..baeaf5b 100644 --- a/auth/tmg/helpers_test.go +++ b/auth/tmg/helpers_test.go @@ -1,6 +1,7 @@ package tmg import ( + "context" "testing" ) @@ -8,7 +9,7 @@ func TestHelpersEdgeCases(t *testing.T) { t.Run("GetAuth/EmptySiteURL", func(t *testing.T) { cnfg := &AuthCnfg{SiteURL: ""} - if _, _, err := GetAuth(cnfg); err == nil { + if _, _, err := GetAuth(context.Background(), cnfg); err == nil { t.Error("empty SiteURL should not go") } }) diff --git a/cmd/pprof/main.go b/cmd/pprof/main.go index 096a4e1..dda4e74 100644 --- a/cmd/pprof/main.go +++ b/cmd/pprof/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "flag" "fmt" "log" @@ -40,7 +41,7 @@ func main() { } func runner(sp *api.SP) { - r, err := sp.Web().Select("Title").Get() + r, err := sp.Web().Select("Title").Get(context.Background()) if err != nil { fmt.Println(err) } diff --git a/cmd/test/main.go b/cmd/test/main.go index d149d36..2b7d865 100644 --- a/cmd/test/main.go +++ b/cmd/test/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "flag" "fmt" "log" @@ -59,7 +60,7 @@ func main() { // Manual test code is below sp := api.NewSP(client) - res, err := sp.Web().Select("Title").Get() + res, err := sp.Web().Select("Title").Get(context.Background()) if err != nil { log.Fatal(err) } @@ -67,7 +68,7 @@ func main() { fmt.Printf("%s\n", res.Data().Title) l := sp.Web().Lists().GetByTitle("Calendar01") - ii, err := l.Items().Select("Id,Title,Created,Editor/Title").Expand("Editor").Get() + ii, err := l.Items().Select("Id,Title,Created,Editor/Title").Expand("Editor").Get(context.Background()) if err != nil { log.Fatal(err) } diff --git a/digest.go b/digest.go index 61327e5..98c0695 100644 --- a/digest.go +++ b/digest.go @@ -34,7 +34,7 @@ func GetDigest(context context.Context, client *SPClient) (string, error) { } contextInfoURL := siteURL + "/_api/ContextInfo" - req, err := http.NewRequest("POST", contextInfoURL, nil) + req, err := http.NewRequestWithContext(context, "POST", contextInfoURL, nil) if err != nil { return "", err } diff --git a/gosip.go b/gosip.go index 661853f..d863278 100644 --- a/gosip.go +++ b/gosip.go @@ -19,6 +19,7 @@ package gosip import ( "bytes" + "context" "fmt" "io" "net/http" @@ -35,7 +36,7 @@ type AuthCnfg interface { // GetAuth Authentication initializer (token/cookie/header, expiration, error) // to support capability for exposing tokens for external tools // e.g. as of this sample project https://github.com/koltyakov/spvault - GetAuth() (string, int64, error) + GetAuth(ctx context.Context) (string, int64, error) // SetAuth Authentication middleware fabric // applies round tripper or enriches requests with authentication and metadata diff --git a/test/helpers/auth.go b/test/helpers/auth.go index ab2850f..27f74a4 100644 --- a/test/helpers/auth.go +++ b/test/helpers/auth.go @@ -1,6 +1,7 @@ package helpers import ( + "context" "fmt" "reflect" "time" @@ -24,7 +25,7 @@ func CheckAuth(auth gosip.AuthCnfg, cnfgPath string, required []string) error { return nil } - token, _, err := auth.GetAuth() + token, _, err := auth.GetAuth(context.Background()) if err != nil { return err } @@ -34,7 +35,7 @@ func CheckAuth(auth gosip.AuthCnfg, cnfgPath string, required []string) error { // Second auth should involve caching and be instant startAt := time.Now() - token, _, err = auth.GetAuth() + token, _, err = auth.GetAuth(context.Background()) if err != nil { return err } diff --git a/test/helpers/transport.go b/test/helpers/transport.go index 2d69baf..d77edad 100644 --- a/test/helpers/transport.go +++ b/test/helpers/transport.go @@ -28,7 +28,7 @@ func CheckTransport(auth gosip.AuthCnfg, cnfgPath string) error { return fmt.Errorf("unable to get digest: %w", err) } - if _, _, err := client.AuthCnfg.GetAuth(); err != nil { + if _, _, err := client.AuthCnfg.GetAuth(context.Background()); err != nil { return err } diff --git a/test/manual/requests.go b/test/manual/requests.go index e8887c4..b72b739 100644 --- a/test/manual/requests.go +++ b/test/manual/requests.go @@ -1,6 +1,7 @@ package manual import ( + "context" "fmt" "strings" @@ -10,12 +11,12 @@ import ( // CheckBasicPost : try creating an item // noinspection GoUnusedExportedFunction -func CheckBasicPost(client *gosip.SPClient) (string, error) { +func CheckBasicPost(ctx context.Context, client *gosip.SPClient) (string, error) { sp := api.NewHTTPClient(client) endpoint := client.AuthCnfg.GetSiteURL() + "/_api/web/lists/getByTitle('Custom')/items" body := `{"__metadata":{"type":"SP.Data.CustomListItem"},"Title":"Test"}` - data, err := sp.Post(endpoint, strings.NewReader(body), nil) + data, err := sp.Post(ctx, endpoint, strings.NewReader(body), nil) if err != nil { return "", fmt.Errorf("unable to read a response: %w", err) } diff --git a/util_test.go b/util_test.go index a54f640..b002068 100644 --- a/util_test.go +++ b/util_test.go @@ -1,6 +1,7 @@ package gosip import ( + "context" "fmt" "io" "net" @@ -25,7 +26,7 @@ func (c *AnonymousCnfg) ParseConfig(bytesValue []byte) error { return nil } func (c *AnonymousCnfg) WriteConfig(privateFile string) error { return nil } // GetAuth : authenticates, receives access token -func (c *AnonymousCnfg) GetAuth() (string, int64, error) { return "", 0, nil } +func (c *AnonymousCnfg) GetAuth(_ context.Context) (string, int64, error) { return "", 0, nil } // GetSiteURL : gets siteURL func (c *AnonymousCnfg) GetSiteURL() string { return c.SiteURL }