diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acc1b68eb..7083e885b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: working-directory: src steps: - uses: actions/checkout@v3 - + # single setup and sum cache handling here. # the results will cascade onto both testing and linting. - name: Setup Golang with cache @@ -239,17 +239,29 @@ jobs: run: working-directory: src steps: - - name: Fail check + - name: Fail check if not repository_dispatch if: github.event_name != 'repository_dispatch' run: | echo "Workflow requires approval from a maintainer to run. It will be automatically rerun on approval." exit 1 + - uses: marocchino/sticky-pull-request-comment@v2 + if: github.event.client_payload.slash_command.args.named.sha != '' && contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.args.named.sha) + with: + message: | + Workflow run sha specified via `ok-to-test` is not the latest commit on PR. Run canceled. + + - name: Fail check if not head of PR + if: github.event.client_payload.slash_command.args.named.sha != '' && contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.args.named.sha) + run: | + echo "Workflow run sha specified is not the latest commit on PR. Exiting." + exit 1 + # add comment to PR with link to workflow run - uses: marocchino/sticky-pull-request-comment@v2 with: message: | - https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID + Test suite run will be available at https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID # Check out merge commit - name: Fork based /ok-to-test checkout diff --git a/.github/workflows/ok-to-test.yml b/.github/workflows/ok-to-test.yml index bd6a7db67..f48e49129 100644 --- a/.github/workflows/ok-to-test.yml +++ b/.github/workflows/ok-to-test.yml @@ -19,7 +19,7 @@ jobs: private_key: ${{ secrets.PRIVATE_KEY }} - name: Slash Command Dispatch - uses: peter-evans/slash-command-dispatch@v1 + uses: peter-evans/slash-command-dispatch@v3 env: TOKEN: ${{ steps.generate_token.outputs.token }} with: @@ -27,5 +27,4 @@ jobs: reaction-token: ${{ secrets.GITHUB_TOKEN }} issue-type: pull-request commands: ok-to-test - named-args: true permission: write diff --git a/.gitignore b/.gitignore index 46f5189b8..911d91a10 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,9 @@ .corso_test.toml .corso.toml +# Logging +.corso.log + # Build directories /bin /docker/bin diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b893cc6..53ec01a36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] (alpha) +### Added + +- Document Corso's fault-tolerance and restartability features +- Add retries on timeouts and status code 500 for Exchange +- Increase page size preference for delta requests for Exchange to reduce number of roundtrips +- OneDrive file/folder permissions can now be backed up and restored +- Add `--restore-permissions` flag to toggle restoration of OneDrive permissions +- Add versions to backups so that we can understand/handle older backup formats + +### Known Issues + +- When the same user has permissions to a file and the containing + folder, we only restore folder level permissions for the user and no + separate file only permission is restored. +- Link shares are not restored + ## [v0.2.0] (alpha) - 2023-1-29 ### Fixed - Check if the user specified for an exchange backup operation has a mailbox. + +### Changed +- Item.Attachments are disabled from being restored for the patching of ([#2353](https://github.com/alcionai/corso/issues/2353)) +- BetaClient introduced. Enables Corso to be able to interact with SharePoint Page objects. Package located `/internal/connector/graph/betasdk` - Handle case where user's drive has not been initialized - Inline attachments (e.g. copy/paste ) are discovered and backed up correctly ([#2163](https://github.com/alcionai/corso/issues/2163)) - Guest and External users (for cloud accounts) and non-on-premise users (for systems that use on-prem AD syncs) are now excluded from backup and restore operations. diff --git a/src/.golangci.yml b/src/.golangci.yml index db883efc4..bda9330be 100644 --- a/src/.golangci.yml +++ b/src/.golangci.yml @@ -3,7 +3,6 @@ run: linters: enable: - - gci - gofmt - gofumpt - errcheck @@ -106,3 +105,14 @@ issues: linters: - forbidigo text: "context.(Background|TODO)" + - path: internal/connector/graph/betasdk + linters: + - wsl + - revive + - gci + - lll + - gofmt + - gofumpt + - misspell + - errcheck + diff --git a/src/cli/backup/onedrive.go b/src/cli/backup/onedrive.go index 60a055dce..9dfb20b79 100644 --- a/src/cli/backup/onedrive.go +++ b/src/cli/backup/onedrive.go @@ -79,6 +79,7 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command { switch cmd.Use { case createCommand: c, fs = utils.AddCommand(cmd, oneDriveCreateCmd()) + options.AddFeatureToggle(cmd, options.EnablePermissionsBackup()) c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix c.Example = oneDriveServiceCommandCreateExamples diff --git a/src/cli/backup/onedrive_integration_test.go b/src/cli/backup/onedrive_integration_test.go index e24cba34f..05231fd11 100644 --- a/src/cli/backup/onedrive_integration_test.go +++ b/src/cli/backup/onedrive_integration_test.go @@ -72,7 +72,13 @@ func (suite *NoBackupOneDriveIntegrationSuite) SetupSuite() { suite.m365UserID = tester.M365UserID(t) // init the repo first - suite.repo, err = repository.Initialize(ctx, suite.acct, suite.st, control.Options{}) + suite.repo, err = repository.Initialize( + ctx, + suite.acct, + suite.st, + control.Options{ + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }) require.NoError(t, err) } @@ -152,7 +158,13 @@ func (suite *BackupDeleteOneDriveIntegrationSuite) SetupSuite() { defer flush() // init the repo first - suite.repo, err = repository.Initialize(ctx, suite.acct, suite.st, control.Options{}) + suite.repo, err = repository.Initialize( + ctx, + suite.acct, + suite.st, + control.Options{ + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }) require.NoError(t, err) m365UserID := tester.M365UserID(t) diff --git a/src/cli/cli.go b/src/cli/cli.go index f06354f0b..77a03b1a7 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -6,7 +6,9 @@ import ( "regexp" "strings" + "github.com/alcionai/clues" "github.com/spf13/cobra" + "golang.org/x/exp/slices" "github.com/alcionai/corso/src/cli/backup" "github.com/alcionai/corso/src/cli/config" @@ -15,6 +17,7 @@ import ( "github.com/alcionai/corso/src/cli/print" "github.com/alcionai/corso/src/cli/repo" "github.com/alcionai/corso/src/cli/restore" + "github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/internal/observe" "github.com/alcionai/corso/src/internal/version" "github.com/alcionai/corso/src/pkg/logger" @@ -31,7 +34,34 @@ var corsoCmd = &cobra.Command{ Short: "Free, Secure, Open-Source Backup for M365.", Long: `Free, Secure, and Open-Source Backup for Microsoft 365.`, RunE: handleCorsoCmd, - PersistentPreRunE: config.InitFunc(), + PersistentPreRunE: preRun, +} + +func preRun(cc *cobra.Command, args []string) error { + if err := config.InitFunc(cc, args); err != nil { + return err + } + + log := logger.Ctx(cc.Context()) + + flags := utils.GetPopulatedFlags(cc) + flagSl := make([]string, 0, len(flags)) + + // currently only tracking flag names to avoid pii leakage. + for f := range flags { + flagSl = append(flagSl, f) + } + + avoidTheseCommands := []string{ + "corso", "env", "help", "backup", "details", "list", "restore", "delete", "repo", "init", "connect", + } + if len(logger.LogFile) > 0 && !slices.Contains(avoidTheseCommands, cc.Use) { + print.Info(cc.Context(), "Logging to file: "+logger.LogFile) + } + + log.Infow("cli command", "command", cc.CommandPath(), "flags", flagSl, "version", version.CurrentVersion()) + + return nil } // Handler for flat calls to `corso`. @@ -39,7 +69,7 @@ var corsoCmd = &cobra.Command{ func handleCorsoCmd(cmd *cobra.Command, args []string) error { v, _ := cmd.Flags().GetBool("version") if v { - print.Outf(cmd.Context(), "Corso version: "+version.Version) + print.Outf(cmd.Context(), "Corso version: "+version.CurrentVersion()) return nil } @@ -62,7 +92,7 @@ func BuildCommandTree(cmd *cobra.Command) { cmd.PersistentFlags().SortFlags = false cmd.Flags().BoolP("version", "v", false, "current version info") - cmd.PersistentPostRunE = config.InitFunc() + cmd.PersistentPreRunE = preRun config.AddConfigFlags(cmd) logger.AddLoggingFlags(cmd) observe.AddProgressBarFlags(cmd) @@ -85,6 +115,7 @@ func BuildCommandTree(cmd *cobra.Command) { // Handle builds and executes the cli processor. func Handle() { + //nolint:forbidigo ctx := config.Seed(context.Background()) ctx = print.SetRootCmd(ctx, corsoCmd) observe.SeedWriter(ctx, print.StderrWriter(ctx), observe.PreloadFlags()) @@ -99,6 +130,9 @@ func Handle() { }() if err := corsoCmd.ExecuteContext(ctx); err != nil { + logger.Ctx(ctx). + With("err", err). + Errorw("cli execution", clues.InErr(err).Slice()...) os.Exit(1) } } diff --git a/src/cli/config/config.go b/src/cli/config/config.go index dbcd21422..8f532abb6 100644 --- a/src/cli/config/config.go +++ b/src/cli/config/config.go @@ -77,20 +77,18 @@ func AddConfigFlags(cmd *cobra.Command) { // InitFunc provides a func that lazily initializes viper and // verifies that the configuration was able to read a file. -func InitFunc() func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { - fp := configFilePathFlag - if len(fp) == 0 || fp == displayDefaultFP { - fp = configFilePath - } - - err := initWithViper(GetViper(cmd.Context()), fp) - if err != nil { - return err - } - - return Read(cmd.Context()) +func InitFunc(cmd *cobra.Command, args []string) error { + fp := configFilePathFlag + if len(fp) == 0 || fp == displayDefaultFP { + fp = configFilePath } + + err := initWithViper(GetViper(cmd.Context()), fp) + if err != nil { + return err + } + + return Read(cmd.Context()) } // initWithViper implements InitConfig, but takes in a viper diff --git a/src/cli/options/options.go b/src/cli/options/options.go index 4988c29ca..2b423836c 100644 --- a/src/cli/options/options.go +++ b/src/cli/options/options.go @@ -11,17 +11,11 @@ import ( func Control() control.Options { opt := control.Defaults() - if fastFail { - opt.FailFast = true - } - - if noStats { - opt.DisableMetrics = true - } - - if disableIncrementals { - opt.ToggleFeatures.DisableIncrementals = true - } + opt.FailFast = fastFail + opt.DisableMetrics = noStats + opt.RestorePermissions = restorePermissions + opt.ToggleFeatures.DisableIncrementals = disableIncrementals + opt.ToggleFeatures.EnablePermissionsBackup = enablePermissionsBackup return opt } @@ -31,8 +25,9 @@ func Control() control.Options { // --------------------------------------------------------------------------- var ( - fastFail bool - noStats bool + fastFail bool + noStats bool + restorePermissions bool ) // AddOperationFlags adds command-local operation flags @@ -49,11 +44,22 @@ func AddGlobalOperationFlags(cmd *cobra.Command) { fs.BoolVar(&noStats, "no-stats", false, "disable anonymous usage statistics gathering") } +// AddRestorePermissionsFlag adds OneDrive flag for restoring permissions +func AddRestorePermissionsFlag(cmd *cobra.Command) { + fs := cmd.Flags() + fs.BoolVar(&restorePermissions, "restore-permissions", false, "Restore permissions for files and folders") + // TODO: reveal this flag once backing up permissions becomes default + cobra.CheckErr(fs.MarkHidden("restore-permissions")) +} + // --------------------------------------------------------------------------- // Feature Flags // --------------------------------------------------------------------------- -var disableIncrementals bool +var ( + disableIncrementals bool + enablePermissionsBackup bool +) type exposeFeatureFlag func(*pflag.FlagSet) @@ -78,3 +84,16 @@ func DisableIncrementals() func(*pflag.FlagSet) { cobra.CheckErr(fs.MarkHidden("disable-incrementals")) } } + +// Adds the hidden '--enable-permissions-backup' cli flag which, when +// set, enables backing up permissions. +func EnablePermissionsBackup() func(*pflag.FlagSet) { + return func(fs *pflag.FlagSet) { + fs.BoolVar( + &enablePermissionsBackup, + "enable-permissions-backup", + false, + "Enable backing up item permissions for OneDrive") + cobra.CheckErr(fs.MarkHidden("enable-permissions-backup")) + } +} diff --git a/src/cli/restore/onedrive.go b/src/cli/restore/onedrive.go index 526db414b..bd8dc7816 100644 --- a/src/cli/restore/onedrive.go +++ b/src/cli/restore/onedrive.go @@ -63,6 +63,9 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command { utils.FileFN, nil, "Restore items by file name or ID") + // permissions restore flag + options.AddRestorePermissionsFlag(c) + // onedrive info flags fs.StringVar( @@ -97,6 +100,9 @@ const ( oneDriveServiceCommandRestoreExamples = `# Restore file with ID 98765abcdef corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abcdef +# Restore file with ID 98765abcdef along with its associated permissions +corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abcdef --restore-permissions + # Restore Alice's file named "FY2021 Planning.xlsx in "Documents/Finance Reports" from a specific backup corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ --user alice@example.com --file "FY2021 Planning.xlsx" --folder "Documents/Finance Reports" diff --git a/src/cmd/factory/impl/common.go b/src/cmd/factory/impl/common.go index 0ea6835dd..78a5dca0e 100644 --- a/src/cmd/factory/impl/common.go +++ b/src/cmd/factory/impl/common.go @@ -16,6 +16,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/mockconnector" "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/pkg/account" + "github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/credentials" @@ -50,6 +51,7 @@ func generateAndRestoreItems( tenantID, userID, destFldr string, howMany int, dbf dataBuilderFunc, + opts control.Options, ) (*details.Details, error) { items := make([]item, 0, howMany) @@ -74,7 +76,7 @@ func generateAndRestoreItems( items: items, }} - // TODO: fit the desination to the containers + // TODO: fit the destination to the containers dest := control.DefaultRestoreDestination(common.SimpleTimeTesting) dest.ContainerName = destFldr @@ -90,7 +92,7 @@ func generateAndRestoreItems( Infof(ctx, "Generating %d %s items in %s\n", howMany, cat, Destination) - return gc.RestoreDataCollections(ctx, acct, sel, dest, dataColls) + return gc.RestoreDataCollections(ctx, backup.Version, acct, sel, dest, opts, dataColls) } // ------------------------------------------------------------------------------------------ diff --git a/src/cmd/factory/impl/exchange.go b/src/cmd/factory/impl/exchange.go index 26f7eef09..39e3c13a1 100644 --- a/src/cmd/factory/impl/exchange.go +++ b/src/cmd/factory/impl/exchange.go @@ -6,6 +6,7 @@ import ( . "github.com/alcionai/corso/src/cli/print" "github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/internal/connector/mockconnector" + "github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/selectors" ) @@ -67,6 +68,7 @@ func handleExchangeEmailFactory(cmd *cobra.Command, args []string) error { subject, body, body, now, now, now, now) }, + control.Options{}, ) if err != nil { return Only(ctx, err) @@ -107,6 +109,7 @@ func handleExchangeCalendarEventFactory(cmd *cobra.Command, args []string) error User, subject, body, body, now, now, false) }, + control.Options{}, ) if err != nil { return Only(ctx, err) @@ -152,6 +155,7 @@ func handleExchangeContactFactory(cmd *cobra.Command, args []string) error { "123-456-7890", ) }, + control.Options{}, ) if err != nil { return Only(ctx, err) diff --git a/src/go.mod b/src/go.mod index 05b801f9f..a149b0201 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,18 +4,19 @@ go 1.19 require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 - github.com/alcionai/clues v0.0.0-20230120231953-1cf61dbafc40 - github.com/aws/aws-sdk-go v1.44.189 + github.com/alcionai/clues v0.0.0-20230131232239-cee86233b005 + github.com/aws/aws-sdk-go v1.44.192 github.com/aws/aws-xray-sdk-go v1.8.0 github.com/google/uuid v1.3.0 github.com/hashicorp/go-multierror v1.1.1 github.com/kopia/kopia v0.12.2-0.20230123092305-e5387cec0acb - github.com/microsoft/kiota-abstractions-go v0.15.2 - github.com/microsoft/kiota-authentication-azure-go v0.5.0 - github.com/microsoft/kiota-http-go v0.11.0 + github.com/microsoft/kiota-abstractions-go v0.16.0 + github.com/microsoft/kiota-authentication-azure-go v0.6.0 + github.com/microsoft/kiota-http-go v0.13.0 + github.com/microsoft/kiota-serialization-form-go v0.2.0 github.com/microsoft/kiota-serialization-json-go v0.7.2 - github.com/microsoftgraph/msgraph-sdk-go v0.50.0 - github.com/microsoftgraph/msgraph-sdk-go-core v0.31.1 + github.com/microsoftgraph/msgraph-sdk-go v0.53.0 + github.com/microsoftgraph/msgraph-sdk-go-core v0.33.0 github.com/pkg/errors v0.9.1 github.com/rudderlabs/analytics-go v3.3.3+incompatible github.com/spatialcurrent/go-lazy v0.0.0-20211115014721-47315cc003d1 @@ -41,7 +42,6 @@ require ( github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/microsoft/kiota-serialization-form-go v0.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/spf13/afero v1.9.3 // indirect @@ -54,8 +54,8 @@ require ( ) require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect @@ -72,7 +72,6 @@ require ( github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.12 // indirect @@ -85,7 +84,7 @@ require ( github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/microsoft/kiota-serialization-text-go v0.6.0 // indirect + github.com/microsoft/kiota-serialization-text-go v0.6.0 github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/minio-go/v7 v7.0.45 // indirect github.com/minio/sha256-simd v1.0.0 // indirect diff --git a/src/go.sum b/src/go.sum index 7813e532d..e32195cbc 100644 --- a/src/go.sum +++ b/src/go.sum @@ -36,12 +36,12 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0 h1:sVW/AFBTGyJxDaMYlq0ct3jUXTtj12tQ6zE2GZUgVQw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1 h1:XUNQ4mw+zJmaA2KXzP9JlQiecy1SI+Eog7xVkPiqIbg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM= github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -52,8 +52,8 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/alcionai/clues v0.0.0-20230120231953-1cf61dbafc40 h1:bvAwz0dcJeIyRjudVyzmmawOvc4SqlSerKd0B4dh0yw= -github.com/alcionai/clues v0.0.0-20230120231953-1cf61dbafc40/go.mod h1:UlAs8jkWIpsOMakiC8NxPgQQVQRdvyf1hYMszlYYLb4= +github.com/alcionai/clues v0.0.0-20230131232239-cee86233b005 h1:eTgICcmcydEWG8J+hgnidf0pzujV3Gd2XqmknykZkzA= +github.com/alcionai/clues v0.0.0-20230131232239-cee86233b005/go.mod h1:UlAs8jkWIpsOMakiC8NxPgQQVQRdvyf1hYMszlYYLb4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -62,8 +62,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/aws/aws-sdk-go v1.44.189 h1:9PBrjndH1uL5AN8818qI3duhQ4hgkMuLvqkJlg9MRyk= -github.com/aws/aws-sdk-go v1.44.189/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.192 h1:KL54vCxRd5v5XBGjnF3FelzXXwl+aWHDmDTihFmRNgM= +github.com/aws/aws-sdk-go v1.44.192/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-xray-sdk-go v1.8.0 h1:0xncHZ588wB/geLjbM/esoW3FOEThWy2TJyb4VXfLFY= github.com/aws/aws-xray-sdk-go v1.8.0/go.mod h1:7LKe47H+j3evfvS1+q0wzpoaGXGrF3mUsfM+thqVO+A= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -211,8 +211,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= -github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -271,22 +269,22 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09 github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microsoft/kiota-abstractions-go v0.15.2 h1:Pp78BbqPvkF2mAMH0Ph37ymwfSH7uF9iYfY1fZ8g630= -github.com/microsoft/kiota-abstractions-go v0.15.2/go.mod h1:RT/s9sCzg49i4iO7e2qhyWmX+DlJDgC0P+Wp8fKQQfo= -github.com/microsoft/kiota-authentication-azure-go v0.5.0 h1:RVA/tTgMnDIN3u4qPZtvYvVRsQDOFkd3yvi6KXjZJko= -github.com/microsoft/kiota-authentication-azure-go v0.5.0/go.mod h1:1Io6h+88FlDRmrajdjSnXPz8oyObUVjNuQZLhrF9kQk= -github.com/microsoft/kiota-http-go v0.11.0 h1:0K0y/wZcTvEEX2Xdj5tngJqknqYQpArLdtjB/fo88Dc= -github.com/microsoft/kiota-http-go v0.11.0/go.mod h1:4D6vMjT7jQ3IRAJrpFoaDtfS9eMaSjQKHY6ETSV2cc0= +github.com/microsoft/kiota-abstractions-go v0.16.0 h1:DZ1L4YsRsQw39iPGnVq2fQkqLXMsazdPwmWsnaH4EZg= +github.com/microsoft/kiota-abstractions-go v0.16.0/go.mod h1:RT/s9sCzg49i4iO7e2qhyWmX+DlJDgC0P+Wp8fKQQfo= +github.com/microsoft/kiota-authentication-azure-go v0.6.0 h1:Il9bLO34J6D8DY89xYAXoGh9muvlphayqG4eihyT6B8= +github.com/microsoft/kiota-authentication-azure-go v0.6.0/go.mod h1:EJCHiLWLXW1/mSgX7lYReAhVO37MzRT5Xi2mcPTwCRQ= +github.com/microsoft/kiota-http-go v0.13.0 h1:CZSC+UrBSwjIvLlVh+AEPsDbD0c17AWd/QPRHIljd8k= +github.com/microsoft/kiota-http-go v0.13.0/go.mod h1:aWtBlFhCetH0JmouvN3hiSaJoqCEdVHPqlrcLYExs3k= github.com/microsoft/kiota-serialization-form-go v0.2.0 h1:jgPE+8DtrWhL+KwnAwRm13HnMNydbelC/NP9wRGwDUo= github.com/microsoft/kiota-serialization-form-go v0.2.0/go.mod h1:chOuh09tO7IrNtubAumdlG5wnrcYdMkjV7joVVGDyGs= github.com/microsoft/kiota-serialization-json-go v0.7.2 h1:DSb4fNDi5O+DqJwrHo+vRy2kSvfxG5VtN6m1EHzn5Vw= github.com/microsoft/kiota-serialization-json-go v0.7.2/go.mod h1:Ojum5prlijopyCOZ2XctRcVlE2pU8h+43r3tMdiWoDU= github.com/microsoft/kiota-serialization-text-go v0.6.0 h1:3N2vftYZlwKdog69AN7ha+FZT0QxPG7xp/hLv0/W2OQ= github.com/microsoft/kiota-serialization-text-go v0.6.0/go.mod h1:OUA4dNH+f6afiJUs+rQAatJos7QVF5PJkyrqoD89lx4= -github.com/microsoftgraph/msgraph-sdk-go v0.50.0 h1:yfPBDr7+tSdq8jKiNCvY5XzQji1kZzOHXvxQ9XxQ4E4= -github.com/microsoftgraph/msgraph-sdk-go v0.50.0/go.mod h1:XoTT9lzRSersVV4/lsFup3sOLfOLEf2dMsLckiAAKq8= -github.com/microsoftgraph/msgraph-sdk-go-core v0.31.1 h1:aVvnO5l8qLCEcvELc5n9grt7UXhAVtpog1QeQKLMlTE= -github.com/microsoftgraph/msgraph-sdk-go-core v0.31.1/go.mod h1:RE4F2qGCTehGtQGc9Txafc4l+XMpbjYuO4amDLFgOWE= +github.com/microsoftgraph/msgraph-sdk-go v0.53.0 h1:HpQd1Nvr8yQNeqhDuiVSbqn1fkHsFbRFDmnuhhXJXOQ= +github.com/microsoftgraph/msgraph-sdk-go v0.53.0/go.mod h1:BZLyon4n4T4EuLIAlX+kJ5JgneFTXVQDah1AJuq3FRY= +github.com/microsoftgraph/msgraph-sdk-go-core v0.33.0 h1:cDL3ov/IZ2ZarUJdGGPsdR+46ALdd3CRAiDBIylLCoA= +github.com/microsoftgraph/msgraph-sdk-go-core v0.33.0/go.mod h1:d0mU3PQAWnN/C4CwPJEZz2QhesrnR5UDnqRu2ODWPkI= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= diff --git a/src/internal/connector/data_collections.go b/src/internal/connector/data_collections.go index 0b6d20b27..410a05462 100644 --- a/src/internal/connector/data_collections.go +++ b/src/internal/connector/data_collections.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/pkg/errors" + "golang.org/x/exp/maps" "github.com/alcionai/corso/src/internal/connector/discovery" "github.com/alcionai/corso/src/internal/connector/discovery/api" @@ -35,27 +36,27 @@ func (gc *GraphConnector) DataCollections( sels selectors.Selector, metadata []data.Collection, ctrlOpts control.Options, -) ([]data.Collection, error) { +) ([]data.Collection, map[string]struct{}, error) { ctx, end := D.Span(ctx, "gc:dataCollections", D.Index("service", sels.Service.String())) defer end() err := verifyBackupInputs(sels, gc.GetUsers(), gc.GetSiteIDs()) if err != nil { - return nil, err + return nil, nil, err } serviceEnabled, err := checkServiceEnabled(ctx, gc.Owners.Users(), path.ServiceType(sels.Service), sels.DiscreteOwner) if err != nil { - return nil, err + return nil, nil, err } if !serviceEnabled { - return []data.Collection{}, nil + return []data.Collection{}, nil, nil } switch sels.Service { case selectors.ServiceExchange: - colls, err := exchange.DataCollections( + colls, excludes, err := exchange.DataCollections( ctx, sels, metadata, @@ -64,7 +65,7 @@ func (gc *GraphConnector) DataCollections( gc.UpdateStatus, ctrlOpts) if err != nil { - return nil, err + return nil, nil, err } for _, c := range colls { @@ -79,13 +80,13 @@ func (gc *GraphConnector) DataCollections( } } - return colls, nil + return colls, excludes, nil case selectors.ServiceOneDrive: - return gc.OneDriveDataCollections(ctx, sels, ctrlOpts) + return gc.OneDriveDataCollections(ctx, sels, metadata, ctrlOpts) case selectors.ServiceSharePoint: - colls, err := sharepoint.DataCollections( + colls, excludes, err := sharepoint.DataCollections( ctx, gc.itemClient, sels, @@ -94,17 +95,17 @@ func (gc *GraphConnector) DataCollections( gc, ctrlOpts) if err != nil { - return nil, err + return nil, nil, err } for range colls { gc.incrementAwaitingMessages() } - return colls, nil + return colls, excludes, nil default: - return nil, errors.Errorf("service %s not supported", sels.Service.String()) + return nil, nil, errors.Errorf("service %s not supported", sels.Service.String()) } } @@ -181,16 +182,18 @@ func (fm odFolderMatcher) Matches(dir string) bool { func (gc *GraphConnector) OneDriveDataCollections( ctx context.Context, selector selectors.Selector, + metadata []data.Collection, ctrlOpts control.Options, -) ([]data.Collection, error) { +) ([]data.Collection, map[string]struct{}, error) { odb, err := selector.ToOneDriveBackup() if err != nil { - return nil, errors.Wrap(err, "oneDriveDataCollection: parsing selector") + return nil, nil, errors.Wrap(err, "oneDriveDataCollection: parsing selector") } var ( user = selector.DiscreteOwner collections = []data.Collection{} + allExcludes = map[string]struct{}{} errs error ) @@ -198,7 +201,7 @@ func (gc *GraphConnector) OneDriveDataCollections( for _, scope := range odb.Scopes() { logger.Ctx(ctx).With("user", user).Debug("Creating OneDrive collections") - odcs, err := onedrive.NewCollections( + odcs, excludes, err := onedrive.NewCollections( gc.itemClient, gc.credentials.AzureTenantID, user, @@ -207,17 +210,19 @@ func (gc *GraphConnector) OneDriveDataCollections( gc.Service, gc.UpdateStatus, ctrlOpts, - ).Get(ctx) + ).Get(ctx, metadata) if err != nil { - return nil, support.WrapAndAppend(user, err, errs) + return nil, nil, support.WrapAndAppend(user, err, errs) } collections = append(collections, odcs...) + + maps.Copy(allExcludes, excludes) } for range collections { gc.incrementAwaitingMessages() } - return collections, errs + return collections, allExcludes, errs } diff --git a/src/internal/connector/data_collections_test.go b/src/internal/connector/data_collections_test.go index 877975bb5..c90bee511 100644 --- a/src/internal/connector/data_collections_test.go +++ b/src/internal/connector/data_collections_test.go @@ -99,7 +99,7 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestExchangeDataCollection for _, test := range tests { suite.T().Run(test.name, func(t *testing.T) { - collections, err := exchange.DataCollections( + collections, excludes, err := exchange.DataCollections( ctx, test.getSelector(t), nil, @@ -108,6 +108,8 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestExchangeDataCollection control.Options{}) require.NoError(t, err) + assert.Empty(t, excludes) + for range collections { connector.incrementAwaitingMessages() } @@ -199,9 +201,10 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestDataCollections_invali for _, test := range tests { suite.T().Run(test.name, func(t *testing.T) { - collections, err := connector.DataCollections(ctx, test.getSelector(t), nil, control.Options{}) + collections, excludes, err := connector.DataCollections(ctx, test.getSelector(t), nil, control.Options{}) assert.Error(t, err) assert.Empty(t, collections) + assert.Empty(t, excludes) }) } } @@ -242,7 +245,7 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestSharePointDataCollecti for _, test := range tests { suite.T().Run(test.name, func(t *testing.T) { - collections, err := sharepoint.DataCollections( + collections, excludes, err := sharepoint.DataCollections( ctx, graph.HTTPClient(graph.NoTimeout()), test.getSelector(), @@ -251,6 +254,8 @@ func (suite *ConnectorDataCollectionIntegrationSuite) TestSharePointDataCollecti connector, control.Options{}) require.NoError(t, err) + // Not expecting excludes as this isn't an incremental backup. + assert.Empty(t, excludes) for range collections { connector.incrementAwaitingMessages() @@ -320,9 +325,11 @@ func (suite *ConnectorCreateSharePointCollectionIntegrationSuite) TestCreateShar sel := selectors.NewSharePointBackup(siteIDs) sel.Include(sel.Libraries([]string{"foo"}, selectors.PrefixMatch())) - cols, err := gc.DataCollections(ctx, sel.Selector, nil, control.Options{}) + cols, excludes, err := gc.DataCollections(ctx, sel.Selector, nil, control.Options{}) require.NoError(t, err) assert.Len(t, cols, 1) + // No excludes yet as this isn't an incremental backup. + assert.Empty(t, excludes) for _, collection := range cols { t.Logf("Path: %s\n", collection.FullPath().String()) @@ -344,9 +351,11 @@ func (suite *ConnectorCreateSharePointCollectionIntegrationSuite) TestCreateShar sel := selectors.NewSharePointBackup(siteIDs) sel.Include(sel.Lists(selectors.Any(), selectors.PrefixMatch())) - cols, err := gc.DataCollections(ctx, sel.Selector, nil, control.Options{}) + cols, excludes, err := gc.DataCollections(ctx, sel.Selector, nil, control.Options{}) require.NoError(t, err) assert.Less(t, 0, len(cols)) + // No excludes yet as this isn't an incremental backup. + assert.Empty(t, excludes) for _, collection := range cols { t.Logf("Path: %s\n", collection.FullPath().String()) diff --git a/src/internal/connector/discovery/api/beta_service.go b/src/internal/connector/discovery/api/beta_service.go new file mode 100644 index 000000000..5ff65ac77 --- /dev/null +++ b/src/internal/connector/discovery/api/beta_service.go @@ -0,0 +1,44 @@ +package api + +import ( + absser "github.com/microsoft/kiota-abstractions-go/serialization" + msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" + "github.com/pkg/errors" + + "github.com/alcionai/corso/src/internal/connector/graph/betasdk" +) + +// Service wraps BetaClient's functionality. +// Abstraction created to comply loosely with graph.Servicer +// methods for ease of switching between v1.0 and beta connnectors +type Service struct { + client *betasdk.BetaClient +} + +func (s Service) Client() *betasdk.BetaClient { + return s.client +} + +func NewBetaService(adpt *msgraphsdk.GraphRequestAdapter) *Service { + return &Service{ + client: betasdk.NewBetaClient(adpt), + } +} + +// Seraialize writes an M365 parsable object into a byte array using the built-in +// application/json writer within the adapter. +func (s Service) Serialize(object absser.Parsable) ([]byte, error) { + writer, err := s.client.Adapter(). + GetSerializationWriterFactory(). + GetSerializationWriter("application/json") + if err != nil || writer == nil { + return nil, errors.Wrap(err, "creating json serialization writer") + } + + err = writer.WriteObjectValue("", object) + if err != nil { + return nil, errors.Wrap(err, "writeObjecValue serialization") + } + + return writer.GetSerializedContent() +} diff --git a/src/internal/connector/discovery/api/beta_service_test.go b/src/internal/connector/discovery/api/beta_service_test.go new file mode 100644 index 000000000..ad67b3877 --- /dev/null +++ b/src/internal/connector/discovery/api/beta_service_test.go @@ -0,0 +1,49 @@ +package api + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + "github.com/alcionai/corso/src/internal/connector/graph" + "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" + "github.com/alcionai/corso/src/internal/tester" +) + +type BetaUnitSuite struct { + suite.Suite +} + +func TestBetaUnitSuite(t *testing.T) { + suite.Run(t, new(BetaUnitSuite)) +} + +func (suite *BetaUnitSuite) TestBetaService_Adapter() { + t := suite.T() + a := tester.NewM365Account(t) + m365, err := a.M365Config() + require.NoError(t, err) + + adpt, err := graph.CreateAdapter( + m365.AzureTenantID, + m365.AzureClientID, + m365.AzureClientSecret, + ) + require.NoError(t, err) + + service := NewBetaService(adpt) + require.NotNil(t, service) + + testPage := models.NewSitePage() + name := "testFile" + desc := "working with parsing" + + testPage.SetName(&name) + testPage.SetDescription(&desc) + + byteArray, err := service.Serialize(testPage) + assert.NotEmpty(t, byteArray) + assert.NoError(t, err) +} diff --git a/src/internal/connector/exchange/api/api.go b/src/internal/connector/exchange/api/api.go index c4858c5c1..c47cc9b5b 100644 --- a/src/internal/connector/exchange/api/api.go +++ b/src/internal/connector/exchange/api/api.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/alcionai/corso/src/internal/connector/graph" + "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/pkg/account" ) @@ -153,3 +154,26 @@ func HasAttachments(body models.ItemBodyable) bool { return strings.Contains(content, "src=\"cid:") } + +// Run a function with retries +func runWithRetry(run func() error) error { + var err error + + for i := 0; i < numberOfRetries; i++ { + err = run() + if err == nil { + return nil + } + + // only retry on timeouts and 500-internal-errors. + if !(graph.IsErrTimeout(err) || graph.IsInternalServerError(err)) { + break + } + + if i < numberOfRetries { + time.Sleep(time.Duration(3*(i+2)) * time.Second) + } + } + + return support.ConnectorStackErrorTraceWrap(err, "maximum retries or unretryable") +} diff --git a/src/internal/connector/exchange/api/contacts.go b/src/internal/connector/exchange/api/contacts.go index 2e9014235..458f364d1 100644 --- a/src/internal/connector/exchange/api/contacts.go +++ b/src/internal/connector/exchange/api/contacts.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/alcionai/clues" "github.com/hashicorp/go-multierror" "github.com/microsoft/kiota-abstractions-go/serialization" kioser "github.com/microsoft/kiota-serialization-json-go" @@ -16,6 +17,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/graph/api" "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/pkg/backup/details" + "github.com/alcionai/corso/src/pkg/selectors" ) // --------------------------------------------------------------------------- @@ -48,9 +50,8 @@ func (c Contacts) CreateContactFolder( return c.stable.Client().UsersById(user).ContactFolders().Post(ctx, requestBody, nil) } -// DeleteContactFolder deletes the ContactFolder associated with the M365 ID if permissions are valid. -// Errors returned if the function call was not successful. -func (c Contacts) DeleteContactFolder( +// DeleteContainer deletes the ContactFolder associated with the M365 ID if permissions are valid. +func (c Contacts) DeleteContainer( ctx context.Context, user, folderID string, ) error { @@ -62,7 +63,16 @@ func (c Contacts) GetItem( ctx context.Context, user, itemID string, ) (serialization.Parsable, *details.ExchangeInfo, error) { - cont, err := c.stable.Client().UsersById(user).ContactsById(itemID).Get(ctx, nil) + var ( + cont models.Contactable + err error + ) + + err = runWithRetry(func() error { + cont, err = c.stable.Client().UsersById(user).ContactsById(itemID).Get(ctx, nil) + return err + }) + if err != nil { return nil, nil, err } @@ -82,7 +92,14 @@ func (c Contacts) GetAllContactFolderNamesForUser( return nil, err } - return c.stable.Client().UsersById(user).ContactFolders().Get(ctx, options) + var resp models.ContactFolderCollectionResponseable + + err = runWithRetry(func() error { + resp, err = c.stable.Client().UsersById(user).ContactFolders().Get(ctx, options) + return err + }) + + return resp, err } func (c Contacts) GetContainerByID( @@ -94,10 +111,14 @@ func (c Contacts) GetContainerByID( return nil, errors.Wrap(err, "options for contact folder") } - return c.stable.Client(). - UsersById(userID). - ContactFoldersById(dirID). - Get(ctx, ofcf) + var resp models.ContactFolderable + + err = runWithRetry(func() error { + resp, err = c.stable.Client().UsersById(userID).ContactFoldersById(dirID).Get(ctx, ofcf) + return err + }) + + return resp, err } // EnumerateContainers iterates through all of the users current @@ -118,6 +139,7 @@ func (c Contacts) EnumerateContainers( var ( errs *multierror.Error + resp models.ContactFolderCollectionResponseable fields = []string{"displayName", "parentFolderId"} ) @@ -132,7 +154,11 @@ func (c Contacts) EnumerateContainers( ChildFolders() for { - resp, err := builder.Get(ctx, ofcf) + err = runWithRetry(func() error { + resp, err = builder.Get(ctx, ofcf) + return err + }) + if err != nil { return errors.Wrap(err, support.ConnectorStackErrorTrace(err)) } @@ -175,7 +201,17 @@ type contactPager struct { } func (p *contactPager) getPage(ctx context.Context) (api.DeltaPageLinker, error) { - return p.builder.Get(ctx, p.options) + var ( + resp api.DeltaPageLinker + err error + ) + + err = runWithRetry(func() error { + resp, err = p.builder.Get(ctx, p.options) + return err + }) + + return resp, err } func (p *contactPager) setNext(nextLink string) { @@ -200,6 +236,11 @@ func (c Contacts) GetAddedAndRemovedItemIDs( resetDelta bool ) + ctx = clues.AddAll( + ctx, + "category", selectors.ExchangeContact, + "folder_id", directoryID) + options, err := optionsForContactFoldersItemDelta([]string{"parentFolderId"}) if err != nil { return nil, nil, DeltaUpdate{}, errors.Wrap(err, "getting query options") diff --git a/src/internal/connector/exchange/api/events.go b/src/internal/connector/exchange/api/events.go index b3e6f9467..70a1a45e9 100644 --- a/src/internal/connector/exchange/api/events.go +++ b/src/internal/connector/exchange/api/events.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/alcionai/clues" "github.com/hashicorp/go-multierror" "github.com/microsoft/kiota-abstractions-go/serialization" kioser "github.com/microsoft/kiota-serialization-json-go" @@ -19,6 +20,7 @@ import ( "github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/logger" "github.com/alcionai/corso/src/pkg/path" + "github.com/alcionai/corso/src/pkg/selectors" ) // --------------------------------------------------------------------------- @@ -50,9 +52,9 @@ func (c Events) CreateCalendar( return c.stable.Client().UsersById(user).Calendars().Post(ctx, requestbody, nil) } -// DeleteCalendar removes calendar from user's M365 account +// DeleteContainer removes a calendar from user's M365 account // Reference: https://docs.microsoft.com/en-us/graph/api/calendar-delete?view=graph-rest-1.0&tabs=go -func (c Events) DeleteCalendar( +func (c Events) DeleteContainer( ctx context.Context, user, calendarID string, ) error { @@ -73,7 +75,13 @@ func (c Events) GetContainerByID( return nil, errors.Wrap(err, "options for event calendar") } - cal, err := service.Client().UsersById(userID).CalendarsById(containerID).Get(ctx, ofc) + var cal models.Calendarable + + err = runWithRetry(func() error { + cal, err = service.Client().UsersById(userID).CalendarsById(containerID).Get(ctx, ofc) + return err + }) + if err != nil { return nil, err } @@ -86,12 +94,28 @@ func (c Events) GetItem( ctx context.Context, user, itemID string, ) (serialization.Parsable, *details.ExchangeInfo, error) { - event, err := c.stable.Client().UsersById(user).EventsById(itemID).Get(ctx, nil) + var ( + event models.Eventable + err error + ) + + err = runWithRetry(func() error { + event, err = c.stable.Client().UsersById(user).EventsById(itemID).Get(ctx, nil) + return err + }) + if err != nil { return nil, nil, err } - var errs *multierror.Error + var ( + errs *multierror.Error + options = &users.ItemEventsItemAttachmentsRequestBuilderGetRequestConfiguration{ + QueryParameters: &users.ItemEventsItemAttachmentsRequestBuilderGetQueryParameters{ + Expand: []string{"microsoft.graph.itemattachment/item"}, + }, + } + ) if *event.GetHasAttachments() || HasAttachments(event.GetBody()) { for count := 0; count < numberOfRetries; count++ { @@ -100,7 +124,7 @@ func (c Events) GetItem( UsersById(user). EventsById(itemID). Attachments(). - Get(ctx, nil) + Get(ctx, options) if err == nil { event.SetAttachments(attached.GetValue()) break @@ -128,7 +152,14 @@ func (c Client) GetAllCalendarNamesForUser( return nil, err } - return c.stable.Client().UsersById(user).Calendars().Get(ctx, options) + var resp models.CalendarCollectionResponseable + + err = runWithRetry(func() error { + resp, err = c.stable.Client().UsersById(user).Calendars().Get(ctx, options) + return err + }) + + return resp, err } // EnumerateContainers iterates through all of the users current @@ -147,7 +178,10 @@ func (c Events) EnumerateContainers( return err } - var errs *multierror.Error + var ( + resp models.CalendarCollectionResponseable + errs *multierror.Error + ) ofc, err := optionsForCalendars([]string{"name"}) if err != nil { @@ -157,7 +191,13 @@ func (c Events) EnumerateContainers( builder := service.Client().UsersById(userID).Calendars() for { - resp, err := builder.Get(ctx, ofc) + var err error + + err = runWithRetry(func() error { + resp, err = builder.Get(ctx, ofc) + return err + }) + if err != nil { return errors.Wrap(err, support.ConnectorStackErrorTrace(err)) } @@ -205,7 +245,16 @@ type eventPager struct { } func (p *eventPager) getPage(ctx context.Context) (api.DeltaPageLinker, error) { - resp, err := p.builder.Get(ctx, p.options) + var ( + resp api.DeltaPageLinker + err error + ) + + err = runWithRetry(func() error { + resp, err = p.builder.Get(ctx, p.options) + return err + }) + return resp, err } @@ -231,6 +280,11 @@ func (c Events) GetAddedAndRemovedItemIDs( errs *multierror.Error ) + ctx = clues.AddAll( + ctx, + "category", selectors.ExchangeEvent, + "calendar_id", calendarID) + if len(oldDelta) > 0 { builder := users.NewItemCalendarsItemEventsDeltaRequestBuilder(oldDelta, service.Adapter()) pgr := &eventPager{service, builder, nil} diff --git a/src/internal/connector/exchange/api/mail.go b/src/internal/connector/exchange/api/mail.go index 4c9d564f0..6acc05162 100644 --- a/src/internal/connector/exchange/api/mail.go +++ b/src/internal/connector/exchange/api/mail.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/alcionai/clues" "github.com/hashicorp/go-multierror" "github.com/microsoft/kiota-abstractions-go/serialization" kioser "github.com/microsoft/kiota-serialization-json-go" @@ -17,6 +18,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/logger" + "github.com/alcionai/corso/src/pkg/selectors" ) // --------------------------------------------------------------------------- @@ -72,9 +74,9 @@ func (c Mail) CreateMailFolderWithParent( Post(ctx, requestBody, nil) } -// DeleteMailFolder removes a mail folder with the corresponding M365 ID from the user's M365 Exchange account +// DeleteContainer removes a mail folder with the corresponding M365 ID from the user's M365 Exchange account // Reference: https://docs.microsoft.com/en-us/graph/api/mailfolder-delete?view=graph-rest-1.0&tabs=http -func (c Mail) DeleteMailFolder( +func (c Mail) DeleteContainer( ctx context.Context, user, folderID string, ) error { @@ -95,7 +97,14 @@ func (c Mail) GetContainerByID( return nil, errors.Wrap(err, "options for mail folder") } - return service.Client().UsersById(userID).MailFoldersById(dirID).Get(ctx, ofmf) + var resp graph.Container + + err = runWithRetry(func() error { + resp, err = service.Client().UsersById(userID).MailFoldersById(dirID).Get(ctx, ofmf) + return err + }) + + return resp, err } // GetItem retrieves a Messageable item. If the item contains an attachment, that @@ -104,7 +113,16 @@ func (c Mail) GetItem( ctx context.Context, user, itemID string, ) (serialization.Parsable, *details.ExchangeInfo, error) { - mail, err := c.stable.Client().UsersById(user).MessagesById(itemID).Get(ctx, nil) + var ( + mail models.Messageable + err error + ) + + err = runWithRetry(func() error { + mail, err = c.stable.Client().UsersById(user).MessagesById(itemID).Get(ctx, nil) + return err + }) + if err != nil { return nil, nil, err } @@ -112,13 +130,18 @@ func (c Mail) GetItem( var errs *multierror.Error if *mail.GetHasAttachments() || HasAttachments(mail.GetBody()) { + options := &users.ItemMessagesItemAttachmentsRequestBuilderGetRequestConfiguration{ + QueryParameters: &users.ItemMessagesItemAttachmentsRequestBuilderGetQueryParameters{ + Expand: []string{"microsoft.graph.itemattachment/item"}, + }, + } for count := 0; count < numberOfRetries; count++ { attached, err := c.largeItem. Client(). UsersById(user). MessagesById(itemID). Attachments(). - Get(ctx, nil) + Get(ctx, options) if err == nil { mail.SetAttachments(attached.GetValue()) break @@ -154,6 +177,7 @@ func (c Mail) EnumerateContainers( } var ( + resp users.ItemMailFoldersDeltaResponseable errs *multierror.Error builder = service.Client(). UsersById(userID). @@ -162,7 +186,13 @@ func (c Mail) EnumerateContainers( ) for { - resp, err := builder.Get(ctx, nil) + var err error + + err = runWithRetry(func() error { + resp, err = builder.Get(ctx, nil) + return err + }) + if err != nil { return errors.Wrap(err, support.ConnectorStackErrorTrace(err)) } @@ -200,7 +230,17 @@ type mailPager struct { } func (p *mailPager) getPage(ctx context.Context) (api.DeltaPageLinker, error) { - return p.builder.Get(ctx, p.options) + var ( + page api.DeltaPageLinker + err error + ) + + err = runWithRetry(func() error { + page, err = p.builder.Get(ctx, p.options) + return err + }) + + return page, err } func (p *mailPager) setNext(nextLink string) { @@ -226,6 +266,11 @@ func (c Mail) GetAddedAndRemovedItemIDs( resetDelta bool ) + ctx = clues.AddAll( + ctx, + "category", selectors.ExchangeMail, + "folder_id", directoryID) + options, err := optionsForFolderMessagesDelta([]string{"isRead"}) if err != nil { return nil, nil, DeltaUpdate{}, errors.Wrap(err, "getting query options") diff --git a/src/internal/connector/exchange/api/options.go b/src/internal/connector/exchange/api/options.go index 49debf334..67725225f 100644 --- a/src/internal/connector/exchange/api/options.go +++ b/src/internal/connector/exchange/api/options.go @@ -3,6 +3,7 @@ package api import ( "fmt" + abstractions "github.com/microsoft/kiota-abstractions-go" "github.com/microsoftgraph/msgraph-sdk-go/users" ) @@ -53,6 +54,16 @@ var ( } ) +const ( + // headerKeyPrefer is used to set query preferences + headerKeyPrefer = "Prefer" + // maxPageSizeHeaderFmt is used to indicate max page size + // preferences + maxPageSizeHeaderFmt = "odata.maxpagesize=%d" + // deltaMaxPageSize is the max page size to use for delta queries + deltaMaxPageSize = 200 +) + // ----------------------------------------------------------------------- // exchange.Query Option Section // These functions can be used to filter a response on M365 @@ -71,8 +82,10 @@ func optionsForFolderMessagesDelta( requestParameters := &users.ItemMailFoldersItemMessagesDeltaRequestBuilderGetQueryParameters{ Select: selecting, } + options := &users.ItemMailFoldersItemMessagesDeltaRequestBuilderGetRequestConfiguration{ QueryParameters: requestParameters, + Headers: buildDeltaRequestHeaders(), } return options, nil @@ -218,6 +231,7 @@ func optionsForContactFoldersItemDelta( options := &users.ItemContactFoldersItemContactsDeltaRequestBuilderGetRequestConfiguration{ QueryParameters: requestParameters, + Headers: buildDeltaRequestHeaders(), } return options, nil @@ -275,3 +289,11 @@ func buildOptions(fields []string, allowed map[string]struct{}) ([]string, error return append(returnedOptions, fields...), nil } + +// buildDeltaRequestHeaders returns the headers we add to delta page requests +func buildDeltaRequestHeaders() *abstractions.RequestHeaders { + headers := abstractions.NewRequestHeaders() + headers.Add(headerKeyPrefer, fmt.Sprintf(maxPageSizeHeaderFmt, deltaMaxPageSize)) + + return headers +} diff --git a/src/internal/connector/exchange/api/shared.go b/src/internal/connector/exchange/api/shared.go index d89ce7411..e4d563e90 100644 --- a/src/internal/connector/exchange/api/shared.go +++ b/src/internal/connector/exchange/api/shared.go @@ -8,6 +8,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/graph/api" "github.com/alcionai/corso/src/internal/connector/support" + "github.com/alcionai/corso/src/pkg/logger" ) // --------------------------------------------------------------------------- @@ -64,6 +65,9 @@ func getItemsAddedAndRemovedFromContainer( deltaURL string ) + itemCount := 0 + page := 0 + for { // get the next page of data, check for standard errors resp, err := pager.getPage(ctx) @@ -82,6 +86,14 @@ func getItemsAddedAndRemovedFromContainer( return nil, nil, "", err } + itemCount += len(items) + page++ + + // Log every ~1000 items (the page size we use is 200) + if page%5 == 0 { + logger.Ctx(ctx).Infow("queried items", "count", itemCount) + } + // iterate through the items in the page for _, item := range items { // if the additional data conains a `@removed` key, the value will either @@ -114,5 +126,7 @@ func getItemsAddedAndRemovedFromContainer( pager.setNext(nextLink) } + logger.Ctx(ctx).Infow("completed enumeration", "count", itemCount) + return addedIDs, removedIDs, deltaURL, nil } diff --git a/src/internal/connector/exchange/attachment.go b/src/internal/connector/exchange/attachment.go index 5cbce271c..6ed05b5df 100644 --- a/src/internal/connector/exchange/attachment.go +++ b/src/internal/connector/exchange/attachment.go @@ -53,6 +53,23 @@ func uploadAttachment( return nil } + // item Attachments to be skipped until the completion of Issue #2353 + if attachmentType == models.ITEM_ATTACHMENTTYPE { + name := "" + if attachment.GetName() != nil { + name = *attachment.GetName() + } + + logger.Ctx(ctx).Infow("item attachment uploads are not supported ", + "attachment_name", name, // TODO: Update to support PII protection + "attachment_type", attachmentType, + "internal_item_type", getItemAttachmentItemType(attachment), + "attachment_id", *attachment.GetId(), + ) + + return nil + } + // For Item/Reference attachments *or* file attachments < 3MB, use the attachments endpoint if attachmentType != models.FILE_ATTACHMENTTYPE || *attachment.GetSize() < largeAttachmentSize { err := uploader.uploadSmallAttachment(ctx, attachment) @@ -90,3 +107,19 @@ func uploadLargeAttachment(ctx context.Context, uploader attachmentUploadable, return nil } + +func getItemAttachmentItemType(query models.Attachmentable) string { + empty := "" + attachment, ok := query.(models.ItemAttachmentable) + + if !ok { + return empty + } + + item := attachment.GetItem() + if item.GetOdataType() == nil { + return empty + } + + return *item.GetOdataType() +} diff --git a/src/internal/connector/exchange/data_collections.go b/src/internal/connector/exchange/data_collections.go index 619d75cee..41bc16301 100644 --- a/src/internal/connector/exchange/data_collections.go +++ b/src/internal/connector/exchange/data_collections.go @@ -167,10 +167,10 @@ func DataCollections( acct account.M365Config, su support.StatusUpdater, ctrlOpts control.Options, -) ([]data.Collection, error) { +) ([]data.Collection, map[string]struct{}, error) { eb, err := selector.ToExchangeBackup() if err != nil { - return nil, errors.Wrap(err, "exchangeDataCollection: parsing selector") + return nil, nil, errors.Wrap(err, "exchangeDataCollection: parsing selector") } var ( @@ -181,7 +181,7 @@ func DataCollections( cdps, err := parseMetadataCollections(ctx, metadata) if err != nil { - return nil, err + return nil, nil, err } for _, scope := range eb.Scopes() { @@ -196,13 +196,15 @@ func DataCollections( ctrlOpts, su) if err != nil { - return nil, support.WrapAndAppend(user, err, errs) + return nil, nil, support.WrapAndAppend(user, err, errs) } collections = append(collections, dcs...) } - return collections, errs + // Exchange does not require adding items to the global exclude list so always + // return nil. + return collections, nil, errs } func getterByType(ac api.Client, category path.CategoryType) (addedAndRemovedItemIDsGetter, error) { diff --git a/src/internal/connector/exchange/restore_test.go b/src/internal/connector/exchange/restore_test.go index f439ea3ad..187d0c127 100644 --- a/src/internal/connector/exchange/restore_test.go +++ b/src/internal/connector/exchange/restore_test.go @@ -76,7 +76,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreContact() { defer func() { // Remove the folder containing contact prior to exiting test - err = suite.ac.Contacts().DeleteContactFolder(ctx, userID, folderID) + err = suite.ac.Contacts().DeleteContainer(ctx, userID, folderID) assert.NoError(t, err) }() @@ -110,7 +110,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreEvent() { defer func() { // Removes calendar containing events created during the test - err = suite.ac.Events().DeleteCalendar(ctx, userID, calendarID) + err = suite.ac.Events().DeleteContainer(ctx, userID, calendarID) assert.NoError(t, err) }() @@ -124,6 +124,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreEvent() { assert.NotNil(t, info, "event item info") } +type containerDeleter interface { + DeleteContainer(context.Context, string, string) error +} + // TestRestoreExchangeObject verifies path.Category usage for restored objects func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { a := tester.NewM365Account(suite.T()) @@ -133,20 +137,24 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { service, err := createService(m365) require.NoError(suite.T(), err) + deleters := map[path.CategoryType]containerDeleter{ + path.EmailCategory: suite.ac.Mail(), + path.ContactsCategory: suite.ac.Contacts(), + path.EventsCategory: suite.ac.Events(), + } + userID := tester.M365UserID(suite.T()) now := time.Now() tests := []struct { name string bytes []byte category path.CategoryType - cleanupFunc func(context.Context, string, string) error destination func(*testing.T, context.Context) string }{ { - name: "Test Mail", - bytes: mockconnector.GetMockMessageBytes("Restore Exchange Object"), - category: path.EmailCategory, - cleanupFunc: suite.ac.Mail().DeleteMailFolder, + name: "Test Mail", + bytes: mockconnector.GetMockMessageBytes("Restore Exchange Object"), + category: path.EmailCategory, destination: func(t *testing.T, ctx context.Context) string { folderName := "TestRestoreMailObject: " + common.FormatSimpleDateTime(now) folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName) @@ -156,10 +164,9 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, }, { - name: "Test Mail: One Direct Attachment", - bytes: mockconnector.GetMockMessageWithDirectAttachment("Restore 1 Attachment"), - category: path.EmailCategory, - cleanupFunc: suite.ac.Mail().DeleteMailFolder, + name: "Test Mail: One Direct Attachment", + bytes: mockconnector.GetMockMessageWithDirectAttachment("Restore 1 Attachment"), + category: path.EmailCategory, destination: func(t *testing.T, ctx context.Context) string { folderName := "TestRestoreMailwithAttachment: " + common.FormatSimpleDateTime(now) folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName) @@ -169,10 +176,21 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, }, { - name: "Test Mail: One Large Attachment", - bytes: mockconnector.GetMockMessageWithLargeAttachment("Restore Large Attachment"), - category: path.EmailCategory, - cleanupFunc: suite.ac.Mail().DeleteMailFolder, + name: "Test Mail: Item Attachment", + bytes: mockconnector.GetMockMessageWithItemAttachmentEvent("Event Item Attachment"), + category: path.EmailCategory, + destination: func(t *testing.T, ctx context.Context) string { + folderName := "TestRestoreMailItemAttachment: " + common.FormatSimpleDateTime(now) + folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName) + require.NoError(t, err) + + return *folder.GetId() + }, + }, + { + name: "Test Mail: One Large Attachment", + bytes: mockconnector.GetMockMessageWithLargeAttachment("Restore Large Attachment"), + category: path.EmailCategory, destination: func(t *testing.T, ctx context.Context) string { folderName := "TestRestoreMailwithLargeAttachment: " + common.FormatSimpleDateTime(now) folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName) @@ -182,10 +200,9 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, }, { - name: "Test Mail: Two Attachments", - bytes: mockconnector.GetMockMessageWithTwoAttachments("Restore 2 Attachments"), - category: path.EmailCategory, - cleanupFunc: suite.ac.Mail().DeleteMailFolder, + name: "Test Mail: Two Attachments", + bytes: mockconnector.GetMockMessageWithTwoAttachments("Restore 2 Attachments"), + category: path.EmailCategory, destination: func(t *testing.T, ctx context.Context) string { folderName := "TestRestoreMailwithAttachments: " + common.FormatSimpleDateTime(now) folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName) @@ -195,10 +212,9 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, }, { - name: "Test Mail: Reference(OneDrive) Attachment", - bytes: mockconnector.GetMessageWithOneDriveAttachment("Restore Reference(OneDrive) Attachment"), - category: path.EmailCategory, - cleanupFunc: suite.ac.Mail().DeleteMailFolder, + name: "Test Mail: Reference(OneDrive) Attachment", + bytes: mockconnector.GetMessageWithOneDriveAttachment("Restore Reference(OneDrive) Attachment"), + category: path.EmailCategory, destination: func(t *testing.T, ctx context.Context) string { folderName := "TestRestoreMailwithReferenceAttachment: " + common.FormatSimpleDateTime(now) folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName) @@ -209,10 +225,9 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, // TODO: #884 - reinstate when able to specify root folder by name { - name: "Test Contact", - bytes: mockconnector.GetMockContactBytes("Test_Omega"), - category: path.ContactsCategory, - cleanupFunc: suite.ac.Contacts().DeleteContactFolder, + name: "Test Contact", + bytes: mockconnector.GetMockContactBytes("Test_Omega"), + category: path.ContactsCategory, destination: func(t *testing.T, ctx context.Context) string { folderName := "TestRestoreContactObject: " + common.FormatSimpleDateTime(now) folder, err := suite.ac.Contacts().CreateContactFolder(ctx, userID, folderName) @@ -222,10 +237,9 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, }, { - name: "Test Events", - bytes: mockconnector.GetDefaultMockEventBytes("Restored Event Object"), - category: path.EventsCategory, - cleanupFunc: suite.ac.Events().DeleteCalendar, + name: "Test Events", + bytes: mockconnector.GetDefaultMockEventBytes("Restored Event Object"), + category: path.EventsCategory, destination: func(t *testing.T, ctx context.Context) string { calendarName := "TestRestoreEventObject: " + common.FormatSimpleDateTime(now) calendar, err := suite.ac.Events().CreateCalendar(ctx, userID, calendarName) @@ -235,10 +249,9 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { }, }, { - name: "Test Event with Attachment", - bytes: mockconnector.GetMockEventWithAttachment("Restored Event Attachment"), - category: path.EventsCategory, - cleanupFunc: suite.ac.Events().DeleteCalendar, + name: "Test Event with Attachment", + bytes: mockconnector.GetMockEventWithAttachment("Restored Event Attachment"), + category: path.EventsCategory, destination: func(t *testing.T, ctx context.Context) string { calendarName := "TestRestoreEventObject_" + common.FormatSimpleDateTime(now) calendar, err := suite.ac.Events().CreateCalendar(ctx, userID, calendarName) @@ -265,10 +278,8 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() { userID, ) assert.NoError(t, err, support.ConnectorStackErrorTrace(err)) - assert.NotNil(t, info, "item info is populated") - - cleanupError := test.cleanupFunc(ctx, userID, destination) - assert.NoError(t, cleanupError) + assert.NotNil(t, info, "item info was not populated") + assert.NoError(t, deleters[test.category].DeleteContainer(ctx, userID, destination)) }) } } diff --git a/src/internal/connector/graph/betasdk/beta_client.go b/src/internal/connector/graph/betasdk/beta_client.go new file mode 100644 index 000000000..f79ab8974 --- /dev/null +++ b/src/internal/connector/graph/betasdk/beta_client.go @@ -0,0 +1,92 @@ +package betasdk + +import ( + absser "github.com/microsoft/kiota-abstractions-go" + kioser "github.com/microsoft/kiota-abstractions-go/serialization" + kform "github.com/microsoft/kiota-serialization-form-go" + kw "github.com/microsoft/kiota-serialization-json-go" + ktext "github.com/microsoft/kiota-serialization-text-go" + msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" + + i1a3c1a5501c5e41b7fd169f2d4c768dce9b096ac28fb5431bf02afcc57295411 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/sites" +) + +// BetaClient the main entry point of the SDK, exposes the configuration and the fluent API. +// Minimal Beta Connector: +// Details on how the Code was generated is present in `kioter-lock.json`. +// NOTE: kiota gen file is altered to indicate what files are included in the created +// +// Changes to Sites Directory: +// Access files send requests with an adapter's with ASync() support. +// This feature is not enabled in v1.0. Manually changed in remaining files. +// Additionally, only calls that begin as client.SitesBy(siteID).Pages() have an endpoint. +// +// The use case specific to Pages(). All other requests should be routed to the /internal/connector/graph.Servicer +// Specifics on `betaClient.SitesById(siteID).Pages` are located: sites/site_item_request_builder.go +// +// Required model files are identified as `modelFiles` in kiota-lock.json. Directory -> betasdk/models +// Required access files are identified as `sitesFiles` in kiota-lock.json. Directory -> betasdk/sites +// +// BetaClient minimal msgraph-beta-sdk-go for connecting to msgraph-beta-sdk-go +// for retrieving `SharePoint.Pages`. Code is generated from kiota.dev. +// requestAdapter is registered with the following the serializers: +// -- "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", +// -- "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", +// -- "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" +type BetaClient struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter *msgraphsdk.GraphRequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// NewBetaClient instantiates a new BetaClient and sets the default values. +// func NewBetaClient(requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter)(*BetaClient) { +func NewBetaClient(requestAdapter *msgraphsdk.GraphRequestAdapter) *BetaClient { + m := &BetaClient{} + m.pathParameters = make(map[string]string) + m.urlTemplate = "{+baseurl}" + m.requestAdapter = requestAdapter + absser.RegisterDefaultSerializer(func() kioser.SerializationWriterFactory { + return kw.NewJsonSerializationWriterFactory() + }) + absser.RegisterDefaultSerializer(func() kioser.SerializationWriterFactory { + return ktext.NewTextSerializationWriterFactory() + }) + absser.RegisterDefaultSerializer(func() kioser.SerializationWriterFactory { + return kform.NewFormSerializationWriterFactory() + }) + absser.RegisterDefaultDeserializer(func() kioser.ParseNodeFactory { + return kw.NewJsonParseNodeFactory() + }) + absser.RegisterDefaultDeserializer(func() kioser.ParseNodeFactory { + return ktext.NewTextParseNodeFactory() + }) + absser.RegisterDefaultDeserializer(func() kioser.ParseNodeFactory { + return kform.NewFormParseNodeFactory() + }) + + if m.requestAdapter.GetBaseUrl() == "" { + m.requestAdapter.SetBaseUrl("https://graph.microsoft.com/beta") + } + return m +} + +// SitesById provides operations to manage the collection of site entities. +func (m *BetaClient) SitesById(id string) *i1a3c1a5501c5e41b7fd169f2d4c768dce9b096ac28fb5431bf02afcc57295411.SiteItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + if id != "" { + urlTplParams["site%2Did"] = id + } + return i1a3c1a5501c5e41b7fd169f2d4c768dce9b096ac28fb5431bf02afcc57295411.NewSiteItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} + +// Adapter() helper method to export Adapter for iterating +func (m *BetaClient) Adapter() *msgraphsdk.GraphRequestAdapter { + return m.requestAdapter +} diff --git a/src/internal/connector/graph/betasdk/beta_client_test.go b/src/internal/connector/graph/betasdk/beta_client_test.go new file mode 100644 index 000000000..84f2db6c5 --- /dev/null +++ b/src/internal/connector/graph/betasdk/beta_client_test.go @@ -0,0 +1,80 @@ +package betasdk + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + "github.com/alcionai/corso/src/internal/connector/graph" + "github.com/alcionai/corso/src/internal/tester" + "github.com/alcionai/corso/src/pkg/account" +) + +type BetaClientSuite struct { + suite.Suite + credentials account.M365Config +} + +func TestBetaClientSuite(t *testing.T) { + suite.Run(t, new(BetaClientSuite)) +} + +func (suite *BetaClientSuite) SetupSuite() { + t := suite.T() + a := tester.NewM365Account(t) + m365, err := a.M365Config() + require.NoError(t, err) + + suite.credentials = m365 +} + +func (suite *BetaClientSuite) TestCreateBetaClient() { + t := suite.T() + adpt, err := graph.CreateAdapter( + suite.credentials.AzureTenantID, + suite.credentials.AzureClientID, + suite.credentials.AzureClientSecret, + ) + + require.NoError(t, err) + + client := NewBetaClient(adpt) + assert.NotNil(t, client) +} + +// TestBasicClientGetFunctionality. Tests that adapter is able +// to parse retrieved Site Page. Additional tests should +// be handled within the /internal/connector/sharepoint when +// additional features are added. +func (suite *BetaClientSuite) TestBasicClientGetFunctionality() { + ctx, flush := tester.NewContext() + defer flush() + t := suite.T() + adpt, err := graph.CreateAdapter( + suite.credentials.AzureTenantID, + suite.credentials.AzureClientID, + suite.credentials.AzureClientSecret, + ) + + require.NoError(t, err) + client := NewBetaClient(adpt) + require.NotNil(t, client) + + siteID := tester.M365SiteID(t) + // TODO(dadams39) document allowable calls in main + collection, err := client.SitesById(siteID).Pages().Get(ctx, nil) + // Ensures that the client is able to receive data from beta + // Not Registered Error: content type application/json does not have a factory registered to be parsed + require.NoError(t, err) + + for _, page := range collection.GetValue() { + assert.NotNil(t, page, "betasdk call for page does not return value.") + + if page != nil { + t.Logf("Page :%s ", *page.GetName()) + assert.NotNil(t, page.GetId()) + } + } +} diff --git a/src/internal/connector/graph/betasdk/kiota-lock.json b/src/internal/connector/graph/betasdk/kiota-lock.json new file mode 100644 index 000000000..21a111aef --- /dev/null +++ b/src/internal/connector/graph/betasdk/kiota-lock.json @@ -0,0 +1,131 @@ +{ + "lockFileVersion": "1.0.0", + "kiotaVersion": "0.10.0.0", + "clientClassName": "BetaClient", + "clientNamespaceName": "github.com/alcionai/corso/src/internal/connector/graph/betasdk", + "language": "Go", + "betaVersion": "0.53.0", + "usesBackingStore": false, + "includeAdditionalData": true, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain", + "application/x-www-form-urlencoded" + ], + "includePatterns": [ + "**/sites/**" + ], + "excludePatterns": [ + "**/admin/**", + "**/users/**", + "**/groups/**", + "**/onenote/**" + ], + "sitesFiles": [ + "count_request_builder.go", + "item_pages_count_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_count_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_horizontal_section_item_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_count_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_horizontal_section_column_item_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_count_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_item_get_position_of_web_part_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_web_part_item_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_item_columns_request_builder.go", + "item_pages_item_canvas_layout_horizontal_sections_request_builder.go", + "item_pages_item_canvas_layout_request_builder.go", + "item_pages_item_canvas_layout_vertical_section_request_builder.go", + "item_pages_item_canvas_layout_vertical_section_webparts_count_request_builder.go", + "item_pages_item_canvas_layout_vertical_section_webparts_item_get_position_of_web_part_request_builder.go", + "item_pages_item_canvas_layout_vertical_section_webparts_request_builder.go", + "item_pages_item_canvas_layout_vertical_section_webparts_web_part_item_request_builder.go", + "item_pages_item_get_web_parts_by_position_post_request_body.go", + "item_pages_item_get_web_parts_by_position_post_request_bodyable.go", + "item_pages_item_get_web_parts_by_position_request_builder.go", + "item_pages_item_get_web_parts_by_position_response.go", + "item_pages_item_get_web_parts_by_position_responseable.go", + "item_pages_item_publish_request_builder.go", + "item_pages_item_web_parts_count_request_builder.go", + "item_pages_item_web_parts_item_get_position_of_web_part_request_builder.go", + "item_pages_item_web_parts_request_builder.go", + "item_pages_item_web_parts_web_part_item_request_builder.go", + "item_pages_request_builder.go", + "item_pages_site_page_item_request_builder.go", + "item_sites_count_request_builder.go", + "item_sites_site_item_request_builder.go", + "site_item_request_builder.go" + ], + "modelFiles":[ + "base_item.go", + "page_layout_type.go", + "standard_web_partable.go", + "canvas_layout.go", + "page_promotion_type.go", + "text_web_part.go", + "canvas_layoutable.go", + "publication_facet.go", + "text_web_part_collection_response.go", + "horizontal_section.go", + "publication_facetable.go", + "text_web_part_collection_responseable.go", + "horizontal_section_collection_response.go", + "reactions_facet.go", + "text_web_partable.go", + "horizontal_section_collection_responseable.go", + "reactions_facetable.go", + "title_area.go", + "horizontal_section_column.go", + "section_emphasis_type.go", + "title_area_layout_type.go", + "horizontal_section_column_collection_response.go", + "server_processed_content.go", + "title_area_text_alignment_type.go", + "horizontal_section_column_collection_responseable.go", + "server_processed_contentable.go", + "title_areaable.go", + "horizontal_section_columnable.go", + "site_access_type.go", + "vertical_section.go", + "horizontal_section_layout_type.go", + "site_page.go", + "vertical_sectionable.go", + "horizontal_sectionable.go", + "site_page_collection_response.go", + "web_part.go", + "meta_data_key_string_pair.go", + "site_page_collection_responseable.go", + "web_part_collection_response.go", + "meta_data_key_string_pair_collection_response.go", + "site_pageable.go", + "web_part_collection_responseable.go", + "meta_data_key_string_pair_collection_responseable.go", + "site_security_level.go", + "web_part_data.go", + "meta_data_key_string_pairable.go", + "site_settings.go", + "web_part_dataable.go", + "meta_data_key_value_pair.go", + "site_settingsable.go", + "web_part_position.go", + "meta_data_key_value_pair_collection_response.go", + "standard_web_part.go", + "web_part_positionable.go", + "meta_data_key_value_pair_collection_responseable.go", + "standard_web_part_collection_response.go", + "web_partable.go", + "meta_data_key_value_pairable.go", + "standard_web_part_collection_responseable.go" + ], + "disabledValidationRules": [] +} diff --git a/src/internal/connector/graph/betasdk/models/base_item.go b/src/internal/connector/graph/betasdk/models/base_item.go new file mode 100644 index 000000000..880262348 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/base_item.go @@ -0,0 +1,379 @@ +package models + +import ( + i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e "time" + + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// BaseItem +type BaseItem struct { + msmodel.Entity + // Identity of the user, device, or application which created the item. Read-only. + createdBy msmodel.IdentitySetable + // The createdByUser property + createdByUser msmodel.Userable + // Date and time of item creation. Read-only. + createdDateTime *i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e.Time + // The description property + description *string + // ETag for the item. Read-only. + eTag *string + // Identity of the user, device, and application which last modified the item. Read-only. + lastModifiedBy msmodel.IdentitySetable + // The lastModifiedByUser property + lastModifiedByUser msmodel.Userable + // Date and time the item was last modified. Read-only. + lastModifiedDateTime *i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e.Time + // The name of the item. Read-write. + name *string + // Parent information, if the item has a parent. Read-write. + parentReference msmodel.ItemReferenceable + // URL that displays the resource in the browser. Read-only. + webUrl *string +} + +// NewBaseItem instantiates a new baseItem and sets the default values. +func NewBaseItem() *BaseItem { + m := &BaseItem{ + Entity: *msmodel.NewEntity(), + } + return m +} + +// CreateBaseItemFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateBaseItemFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + if parseNode != nil { + mappingValueNode, err := parseNode.GetChildNode("@odata.type") + if err != nil { + return nil, err + } + if mappingValueNode != nil { + mappingValue, err := mappingValueNode.GetStringValue() + if err != nil { + return nil, err + } + if mappingValue != nil { + switch *mappingValue { + case "#microsoft.graph.drive": + return msmodel.NewDrive(), nil + case "#microsoft.graph.driveItem": + return msmodel.NewDriveItem(), nil + case "#microsoft.graph.list": + return msmodel.NewList(), nil + case "#microsoft.graph.listItem": + return msmodel.NewListItem(), nil + case "#microsoft.graph.sharedDriveItem": + return msmodel.NewSharedDriveItem(), nil + case "#microsoft.graph.site": + return msmodel.NewSite(), nil + case "#microsoft.graph.sitePage": + return NewSitePage(), nil + } + } + } + } + return NewBaseItem(), nil +} + +// GetCreatedBy gets the createdBy property value. Identity of the user, device, or application which created the item. Read-only. +func (m *BaseItem) GetCreatedBy() msmodel.IdentitySetable { + return m.createdBy +} + +// GetCreatedByUser gets the createdByUser property value. The createdByUser property +func (m *BaseItem) GetCreatedByUser() msmodel.Userable { + return m.createdByUser +} + +// GetCreatedDateTime gets the createdDateTime property value. Date and time of item creation. Read-only. +func (m *BaseItem) GetCreatedDateTime() *i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e.Time { + return m.createdDateTime +} + +// GetDescription gets the description property value. The description property +func (m *BaseItem) GetDescription() *string { + return m.description +} + +// GetETag gets the eTag property value. ETag for the item. Read-only. +func (m *BaseItem) GetETag() *string { + return m.eTag +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *BaseItem) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.Entity.GetFieldDeserializers() + res["createdBy"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateIdentitySetFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetCreatedBy(val.(msmodel.IdentitySetable)) + } + return nil + } + res["createdByUser"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateUserFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetCreatedByUser(val.(msmodel.Userable)) + } + return nil + } + res["createdDateTime"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetTimeValue() + if err != nil { + return err + } + if val != nil { + m.SetCreatedDateTime(val) + } + return nil + } + res["description"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetDescription(val) + } + return nil + } + res["eTag"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetETag(val) + } + return nil + } + res["lastModifiedBy"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateIdentitySetFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetLastModifiedBy(val.(msmodel.IdentitySetable)) + } + return nil + } + res["lastModifiedByUser"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateUserFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetLastModifiedByUser(val.(msmodel.Userable)) + } + return nil + } + res["lastModifiedDateTime"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetTimeValue() + if err != nil { + return err + } + if val != nil { + m.SetLastModifiedDateTime(val) + } + return nil + } + res["name"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetName(val) + } + return nil + } + res["parentReference"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateItemReferenceFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetParentReference(val.(msmodel.ItemReferenceable)) + } + return nil + } + res["webUrl"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetWebUrl(val) + } + return nil + } + return res +} + +// GetLastModifiedBy gets the lastModifiedBy property value. Identity of the user, device, and application which last modified the item. Read-only. +func (m *BaseItem) GetLastModifiedBy() msmodel.IdentitySetable { + return m.lastModifiedBy +} + +// GetLastModifiedByUser gets the lastModifiedByUser property value. The lastModifiedByUser property +func (m *BaseItem) GetLastModifiedByUser() msmodel.Userable { + return m.lastModifiedByUser +} + +// GetLastModifiedDateTime gets the lastModifiedDateTime property value. Date and time the item was last modified. Read-only. +func (m *BaseItem) GetLastModifiedDateTime() *i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e.Time { + return m.lastModifiedDateTime +} + +// GetName gets the name property value. The name of the item. Read-write. +func (m *BaseItem) GetName() *string { + return m.name +} + +// GetParentReference gets the parentReference property value. Parent information, if the item has a parent. Read-write. +func (m *BaseItem) GetParentReference() msmodel.ItemReferenceable { + return m.parentReference +} + +// GetWebUrl gets the webUrl property value. URL that displays the resource in the browser. Read-only. +func (m *BaseItem) GetWebUrl() *string { + return m.webUrl +} + +// Serialize serializes information the current object +func (m *BaseItem) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.Entity.Serialize(writer) + if err != nil { + return err + } + { + err = writer.WriteObjectValue("createdBy", m.GetCreatedBy()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("createdByUser", m.GetCreatedByUser()) + if err != nil { + return err + } + } + { + err = writer.WriteTimeValue("createdDateTime", m.GetCreatedDateTime()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("description", m.GetDescription()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("eTag", m.GetETag()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("lastModifiedBy", m.GetLastModifiedBy()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("lastModifiedByUser", m.GetLastModifiedByUser()) + if err != nil { + return err + } + } + { + err = writer.WriteTimeValue("lastModifiedDateTime", m.GetLastModifiedDateTime()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("name", m.GetName()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("parentReference", m.GetParentReference()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("webUrl", m.GetWebUrl()) + if err != nil { + return err + } + } + return nil +} + +// SetCreatedBy sets the createdBy property value. Identity of the user, device, or application which created the item. Read-only. +func (m *BaseItem) SetCreatedBy(value msmodel.IdentitySetable) { + m.createdBy = value +} + +// SetCreatedByUser sets the createdByUser property value. The createdByUser property +func (m *BaseItem) SetCreatedByUser(value msmodel.Userable) { + m.createdByUser = value +} + +// SetCreatedDateTime sets the createdDateTime property value. Date and time of item creation. Read-only. +func (m *BaseItem) SetCreatedDateTime(value *i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e.Time) { + m.createdDateTime = value +} + +// SetDescription sets the description property value. The description property +func (m *BaseItem) SetDescription(value *string) { + m.description = value +} + +// SetETag sets the eTag property value. ETag for the item. Read-only. +func (m *BaseItem) SetETag(value *string) { + m.eTag = value +} + +// SetLastModifiedBy sets the lastModifiedBy property value. Identity of the user, device, and application which last modified the item. Read-only. +func (m *BaseItem) SetLastModifiedBy(value msmodel.IdentitySetable) { + m.lastModifiedBy = value +} + +// SetLastModifiedByUser sets the lastModifiedByUser property value. The lastModifiedByUser property +func (m *BaseItem) SetLastModifiedByUser(value msmodel.Userable) { + m.lastModifiedByUser = value +} + +// SetLastModifiedDateTime sets the lastModifiedDateTime property value. Date and time the item was last modified. Read-only. +func (m *BaseItem) SetLastModifiedDateTime(value *i336074805fc853987abe6f7fe3ad97a6a6f3077a16391fec744f671a015fbd7e.Time) { + m.lastModifiedDateTime = value +} + +// SetName sets the name property value. The name of the item. Read-write. +func (m *BaseItem) SetName(value *string) { + m.name = value +} + +// SetParentReference sets the parentReference property value. Parent information, if the item has a parent. Read-write. +func (m *BaseItem) SetParentReference(value msmodel.ItemReferenceable) { + m.parentReference = value +} + +// SetWebUrl sets the webUrl property value. URL that displays the resource in the browser. Read-only. +func (m *BaseItem) SetWebUrl(value *string) { + m.webUrl = value +} diff --git a/src/internal/connector/graph/betasdk/models/canvas_layout.go b/src/internal/connector/graph/betasdk/models/canvas_layout.go new file mode 100644 index 000000000..cda577a77 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/canvas_layout.go @@ -0,0 +1,103 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// CanvasLayout +type CanvasLayout struct { + msmodel.Entity + // Collection of horizontal sections on the SharePoint page. + horizontalSections []HorizontalSectionable + // Vertical section on the SharePoint page. + verticalSection VerticalSectionable +} + +// NewCanvasLayout instantiates a new canvasLayout and sets the default values. +func NewCanvasLayout() *CanvasLayout { + m := &CanvasLayout{ + Entity: *msmodel.NewEntity(), + } + return m +} + +// CreateCanvasLayoutFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateCanvasLayoutFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewCanvasLayout(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *CanvasLayout) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.Entity.GetFieldDeserializers() + res["horizontalSections"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateHorizontalSectionFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]HorizontalSectionable, len(val)) + for i, v := range val { + res[i] = v.(HorizontalSectionable) + } + m.SetHorizontalSections(res) + } + return nil + } + res["verticalSection"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateVerticalSectionFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetVerticalSection(val.(VerticalSectionable)) + } + return nil + } + return res +} + +// GetHorizontalSections gets the horizontalSections property value. Collection of horizontal sections on the SharePoint page. +func (m *CanvasLayout) GetHorizontalSections() []HorizontalSectionable { + return m.horizontalSections +} + +// GetVerticalSection gets the verticalSection property value. Vertical section on the SharePoint page. +func (m *CanvasLayout) GetVerticalSection() VerticalSectionable { + return m.verticalSection +} + +// Serialize serializes information the current object +func (m *CanvasLayout) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.Entity.Serialize(writer) + if err != nil { + return err + } + if m.GetHorizontalSections() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetHorizontalSections())) + for i, v := range m.GetHorizontalSections() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("horizontalSections", cast) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("verticalSection", m.GetVerticalSection()) + if err != nil { + return err + } + } + return nil +} + +// SetHorizontalSections sets the horizontalSections property value. Collection of horizontal sections on the SharePoint page. +func (m *CanvasLayout) SetHorizontalSections(value []HorizontalSectionable) { + m.horizontalSections = value +} + +// SetVerticalSection sets the verticalSection property value. Vertical section on the SharePoint page. +func (m *CanvasLayout) SetVerticalSection(value VerticalSectionable) { + m.verticalSection = value +} diff --git a/src/internal/connector/graph/betasdk/models/canvas_layoutable.go b/src/internal/connector/graph/betasdk/models/canvas_layoutable.go new file mode 100644 index 000000000..537d5b0df --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/canvas_layoutable.go @@ -0,0 +1,16 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// CanvasLayoutable +type CanvasLayoutable interface { + msmodel.Entityable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetHorizontalSections() []HorizontalSectionable + GetVerticalSection() VerticalSectionable + SetHorizontalSections(value []HorizontalSectionable) + SetVerticalSection(value VerticalSectionable) +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section.go b/src/internal/connector/graph/betasdk/models/horizontal_section.go new file mode 100644 index 000000000..3e143d40f --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section.go @@ -0,0 +1,133 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSection provides operations to call the remove method. +type HorizontalSection struct { + msmodel.Entity + // The set of vertical columns in this section. + columns []HorizontalSectionColumnable + // Enumeration value that indicates the emphasis of the section background. The possible values are: none, netural, soft, strong, unknownFutureValue. + emphasis *SectionEmphasisType + // Layout type of the section. The possible values are: none, oneColumn, twoColumns, threeColumns, oneThirdLeftColumn, oneThirdRightColumn, fullWidth, unknownFutureValue. + layout *HorizontalSectionLayoutType +} + +// NewHorizontalSection instantiates a new horizontalSection and sets the default values. +func NewHorizontalSection() *HorizontalSection { + m := &HorizontalSection{ + Entity: *msmodel.NewEntity(), + } + return m +} + +// CreateHorizontalSectionFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateHorizontalSectionFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewHorizontalSection(), nil +} + +// GetColumns gets the columns property value. The set of vertical columns in this section. +func (m *HorizontalSection) GetColumns() []HorizontalSectionColumnable { + return m.columns +} + +// GetEmphasis gets the emphasis property value. Enumeration value that indicates the emphasis of the section background. The possible values are: none, netural, soft, strong, unknownFutureValue. +func (m *HorizontalSection) GetEmphasis() *SectionEmphasisType { + return m.emphasis +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *HorizontalSection) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.Entity.GetFieldDeserializers() + res["columns"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateHorizontalSectionColumnFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]HorizontalSectionColumnable, len(val)) + for i, v := range val { + res[i] = v.(HorizontalSectionColumnable) + } + m.SetColumns(res) + } + return nil + } + res["emphasis"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParseSectionEmphasisType) + if err != nil { + return err + } + if val != nil { + m.SetEmphasis(val.(*SectionEmphasisType)) + } + return nil + } + res["layout"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParseHorizontalSectionLayoutType) + if err != nil { + return err + } + if val != nil { + m.SetLayout(val.(*HorizontalSectionLayoutType)) + } + return nil + } + return res +} + +// GetLayout gets the layout property value. Layout type of the section. The possible values are: none, oneColumn, twoColumns, threeColumns, oneThirdLeftColumn, oneThirdRightColumn, fullWidth, unknownFutureValue. +func (m *HorizontalSection) GetLayout() *HorizontalSectionLayoutType { + return m.layout +} + +// Serialize serializes information the current object +func (m *HorizontalSection) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.Entity.Serialize(writer) + if err != nil { + return err + } + if m.GetColumns() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetColumns())) + for i, v := range m.GetColumns() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("columns", cast) + if err != nil { + return err + } + } + if m.GetEmphasis() != nil { + cast := (*m.GetEmphasis()).String() + err = writer.WriteStringValue("emphasis", &cast) + if err != nil { + return err + } + } + if m.GetLayout() != nil { + cast := (*m.GetLayout()).String() + err = writer.WriteStringValue("layout", &cast) + if err != nil { + return err + } + } + return nil +} + +// SetColumns sets the columns property value. The set of vertical columns in this section. +func (m *HorizontalSection) SetColumns(value []HorizontalSectionColumnable) { + m.columns = value +} + +// SetEmphasis sets the emphasis property value. Enumeration value that indicates the emphasis of the section background. The possible values are: none, netural, soft, strong, unknownFutureValue. +func (m *HorizontalSection) SetEmphasis(value *SectionEmphasisType) { + m.emphasis = value +} + +// SetLayout sets the layout property value. Layout type of the section. The possible values are: none, oneColumn, twoColumns, threeColumns, oneThirdLeftColumn, oneThirdRightColumn, fullWidth, unknownFutureValue. +func (m *HorizontalSection) SetLayout(value *HorizontalSectionLayoutType) { + m.layout = value +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_collection_response.go b/src/internal/connector/graph/betasdk/models/horizontal_section_collection_response.go new file mode 100644 index 000000000..70fb40959 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionCollectionResponse +type HorizontalSectionCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []HorizontalSectionable +} + +// NewHorizontalSectionCollectionResponse instantiates a new HorizontalSectionCollectionResponse and sets the default values. +func NewHorizontalSectionCollectionResponse() *HorizontalSectionCollectionResponse { + m := &HorizontalSectionCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateHorizontalSectionCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateHorizontalSectionCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewHorizontalSectionCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *HorizontalSectionCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateHorizontalSectionFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]HorizontalSectionable, len(val)) + for i, v := range val { + res[i] = v.(HorizontalSectionable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *HorizontalSectionCollectionResponse) GetValue() []HorizontalSectionable { + return m.value +} + +// Serialize serializes information the current object +func (m *HorizontalSectionCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *HorizontalSectionCollectionResponse) SetValue(value []HorizontalSectionable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_collection_responseable.go b/src/internal/connector/graph/betasdk/models/horizontal_section_collection_responseable.go new file mode 100644 index 000000000..a46d55060 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionCollectionResponseable +type HorizontalSectionCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []HorizontalSectionable + SetValue(value []HorizontalSectionable) +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_column.go b/src/internal/connector/graph/betasdk/models/horizontal_section_column.go new file mode 100644 index 000000000..f00261c16 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_column.go @@ -0,0 +1,103 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionColumn provides operations to call the remove method. +type HorizontalSectionColumn struct { + msmodel.Entity + // The collection of WebParts in this column. + webparts []WebPartable + // Width of the column. A horizontal section is divided into 12 grids. A column should have a value of 1-12 to represent its range spans. For example, there can be two columns both have a width of 6 in a section. + width *int32 +} + +// NewHorizontalSectionColumn instantiates a new horizontalSectionColumn and sets the default values. +func NewHorizontalSectionColumn() *HorizontalSectionColumn { + m := &HorizontalSectionColumn{ + Entity: *msmodel.NewEntity(), + } + return m +} + +// CreateHorizontalSectionColumnFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateHorizontalSectionColumnFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewHorizontalSectionColumn(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *HorizontalSectionColumn) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.Entity.GetFieldDeserializers() + res["webparts"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]WebPartable, len(val)) + for i, v := range val { + res[i] = v.(WebPartable) + } + m.SetWebparts(res) + } + return nil + } + res["width"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetInt32Value() + if err != nil { + return err + } + if val != nil { + m.SetWidth(val) + } + return nil + } + return res +} + +// GetWebparts gets the webparts property value. The collection of WebParts in this column. +func (m *HorizontalSectionColumn) GetWebparts() []WebPartable { + return m.webparts +} + +// GetWidth gets the width property value. Width of the column. A horizontal section is divided into 12 grids. A column should have a value of 1-12 to represent its range spans. For example, there can be two columns both have a width of 6 in a section. +func (m *HorizontalSectionColumn) GetWidth() *int32 { + return m.width +} + +// Serialize serializes information the current object +func (m *HorizontalSectionColumn) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.Entity.Serialize(writer) + if err != nil { + return err + } + if m.GetWebparts() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetWebparts())) + for i, v := range m.GetWebparts() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("webparts", cast) + if err != nil { + return err + } + } + { + err = writer.WriteInt32Value("width", m.GetWidth()) + if err != nil { + return err + } + } + return nil +} + +// SetWebparts sets the webparts property value. The collection of WebParts in this column. +func (m *HorizontalSectionColumn) SetWebparts(value []WebPartable) { + m.webparts = value +} + +// SetWidth sets the width property value. Width of the column. A horizontal section is divided into 12 grids. A column should have a value of 1-12 to represent its range spans. For example, there can be two columns both have a width of 6 in a section. +func (m *HorizontalSectionColumn) SetWidth(value *int32) { + m.width = value +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_column_collection_response.go b/src/internal/connector/graph/betasdk/models/horizontal_section_column_collection_response.go new file mode 100644 index 000000000..081244d8f --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_column_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionColumnCollectionResponse +type HorizontalSectionColumnCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []HorizontalSectionColumnable +} + +// NewHorizontalSectionColumnCollectionResponse instantiates a new HorizontalSectionColumnCollectionResponse and sets the default values. +func NewHorizontalSectionColumnCollectionResponse() *HorizontalSectionColumnCollectionResponse { + m := &HorizontalSectionColumnCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateHorizontalSectionColumnCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateHorizontalSectionColumnCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewHorizontalSectionColumnCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *HorizontalSectionColumnCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateHorizontalSectionColumnFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]HorizontalSectionColumnable, len(val)) + for i, v := range val { + res[i] = v.(HorizontalSectionColumnable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *HorizontalSectionColumnCollectionResponse) GetValue() []HorizontalSectionColumnable { + return m.value +} + +// Serialize serializes information the current object +func (m *HorizontalSectionColumnCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *HorizontalSectionColumnCollectionResponse) SetValue(value []HorizontalSectionColumnable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_column_collection_responseable.go b/src/internal/connector/graph/betasdk/models/horizontal_section_column_collection_responseable.go new file mode 100644 index 000000000..b52c33b35 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_column_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionColumnCollectionResponseable +type HorizontalSectionColumnCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []HorizontalSectionColumnable + SetValue(value []HorizontalSectionColumnable) +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_columnable.go b/src/internal/connector/graph/betasdk/models/horizontal_section_columnable.go new file mode 100644 index 000000000..f4f185a4a --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_columnable.go @@ -0,0 +1,16 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionColumnable +type HorizontalSectionColumnable interface { + msmodel.Entityable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetWebparts() []WebPartable + GetWidth() *int32 + SetWebparts(value []WebPartable) + SetWidth(value *int32) +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_section_layout_type.go b/src/internal/connector/graph/betasdk/models/horizontal_section_layout_type.go new file mode 100644 index 000000000..80e208ffe --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_section_layout_type.go @@ -0,0 +1,54 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type HorizontalSectionLayoutType int + +const ( + NONE_HORIZONTALSECTIONLAYOUTTYPE HorizontalSectionLayoutType = iota + ONECOLUMN_HORIZONTALSECTIONLAYOUTTYPE + TWOCOLUMNS_HORIZONTALSECTIONLAYOUTTYPE + THREECOLUMNS_HORIZONTALSECTIONLAYOUTTYPE + ONETHIRDLEFTCOLUMN_HORIZONTALSECTIONLAYOUTTYPE + ONETHIRDRIGHTCOLUMN_HORIZONTALSECTIONLAYOUTTYPE + FULLWIDTH_HORIZONTALSECTIONLAYOUTTYPE + UNKNOWNFUTUREVALUE_HORIZONTALSECTIONLAYOUTTYPE +) + +func (i HorizontalSectionLayoutType) String() string { + return []string{"none", "oneColumn", "twoColumns", "threeColumns", "oneThirdLeftColumn", "oneThirdRightColumn", "fullWidth", "unknownFutureValue"}[i] +} +func ParseHorizontalSectionLayoutType(v string) (interface{}, error) { + result := NONE_HORIZONTALSECTIONLAYOUTTYPE + switch v { + case "none": + result = NONE_HORIZONTALSECTIONLAYOUTTYPE + case "oneColumn": + result = ONECOLUMN_HORIZONTALSECTIONLAYOUTTYPE + case "twoColumns": + result = TWOCOLUMNS_HORIZONTALSECTIONLAYOUTTYPE + case "threeColumns": + result = THREECOLUMNS_HORIZONTALSECTIONLAYOUTTYPE + case "oneThirdLeftColumn": + result = ONETHIRDLEFTCOLUMN_HORIZONTALSECTIONLAYOUTTYPE + case "oneThirdRightColumn": + result = ONETHIRDRIGHTCOLUMN_HORIZONTALSECTIONLAYOUTTYPE + case "fullWidth": + result = FULLWIDTH_HORIZONTALSECTIONLAYOUTTYPE + case "unknownFutureValue": + result = UNKNOWNFUTUREVALUE_HORIZONTALSECTIONLAYOUTTYPE + default: + return 0, errors.New("Unknown HorizontalSectionLayoutType value: " + v) + } + return &result, nil +} +func SerializeHorizontalSectionLayoutType(values []HorizontalSectionLayoutType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/horizontal_sectionable.go b/src/internal/connector/graph/betasdk/models/horizontal_sectionable.go new file mode 100644 index 000000000..5ed926080 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/horizontal_sectionable.go @@ -0,0 +1,18 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// HorizontalSectionable +type HorizontalSectionable interface { + msmodel.Entityable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetColumns() []HorizontalSectionColumnable + GetEmphasis() *SectionEmphasisType + GetLayout() *HorizontalSectionLayoutType + SetColumns(value []HorizontalSectionColumnable) + SetEmphasis(value *SectionEmphasisType) + SetLayout(value *HorizontalSectionLayoutType) +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair.go b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair.go new file mode 100644 index 000000000..c79f17cfb --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair.go @@ -0,0 +1,134 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// MetaDataKeyStringPair +type MetaDataKeyStringPair struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // Key of the meta data. + key *string + // The OdataType property + odataType *string + // Value of the meta data. + value *string +} + +// NewMetaDataKeyStringPair instantiates a new metaDataKeyStringPair and sets the default values. +func NewMetaDataKeyStringPair() *MetaDataKeyStringPair { + m := &MetaDataKeyStringPair{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateMetaDataKeyStringPairFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateMetaDataKeyStringPairFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewMetaDataKeyStringPair(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *MetaDataKeyStringPair) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *MetaDataKeyStringPair) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["key"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetKey(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetValue(val) + } + return nil + } + return res +} + +// GetKey gets the key property value. Key of the meta data. +func (m *MetaDataKeyStringPair) GetKey() *string { + return m.key +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *MetaDataKeyStringPair) GetOdataType() *string { + return m.odataType +} + +// GetValue gets the value property value. Value of the meta data. +func (m *MetaDataKeyStringPair) GetValue() *string { + return m.value +} + +// Serialize serializes information the current object +func (m *MetaDataKeyStringPair) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteStringValue("key", m.GetKey()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("value", m.GetValue()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *MetaDataKeyStringPair) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetKey sets the key property value. Key of the meta data. +func (m *MetaDataKeyStringPair) SetKey(value *string) { + m.key = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *MetaDataKeyStringPair) SetOdataType(value *string) { + m.odataType = value +} + +// SetValue sets the value property value. Value of the meta data. +func (m *MetaDataKeyStringPair) SetValue(value *string) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair_collection_response.go b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair_collection_response.go new file mode 100644 index 000000000..b5c88ce49 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// MetaDataKeyStringPairCollectionResponse +type MetaDataKeyStringPairCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []MetaDataKeyStringPairable +} + +// NewMetaDataKeyStringPairCollectionResponse instantiates a new MetaDataKeyStringPairCollectionResponse and sets the default values. +func NewMetaDataKeyStringPairCollectionResponse() *MetaDataKeyStringPairCollectionResponse { + m := &MetaDataKeyStringPairCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateMetaDataKeyStringPairCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateMetaDataKeyStringPairCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewMetaDataKeyStringPairCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *MetaDataKeyStringPairCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyStringPairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyStringPairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyStringPairable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *MetaDataKeyStringPairCollectionResponse) GetValue() []MetaDataKeyStringPairable { + return m.value +} + +// Serialize serializes information the current object +func (m *MetaDataKeyStringPairCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *MetaDataKeyStringPairCollectionResponse) SetValue(value []MetaDataKeyStringPairable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair_collection_responseable.go b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair_collection_responseable.go new file mode 100644 index 000000000..ad657d982 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pair_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// MetaDataKeyStringPairCollectionResponseable +type MetaDataKeyStringPairCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []MetaDataKeyStringPairable + SetValue(value []MetaDataKeyStringPairable) +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_string_pairable.go b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pairable.go new file mode 100644 index 000000000..4168f4dce --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_string_pairable.go @@ -0,0 +1,17 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// MetaDataKeyStringPairable +type MetaDataKeyStringPairable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetKey() *string + GetOdataType() *string + GetValue() *string + SetKey(value *string) + SetOdataType(value *string) + SetValue(value *string) +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair.go b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair.go new file mode 100644 index 000000000..a64ebdf0d --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair.go @@ -0,0 +1,135 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// MetaDataKeyValuePair +type MetaDataKeyValuePair struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // Key of the metadata. + key *string + // The OdataType property + odataType *string + // Value of the metadata. Should be an object. + value msmodel.Jsonable +} + +// NewMetaDataKeyValuePair instantiates a new metaDataKeyValuePair and sets the default values. +func NewMetaDataKeyValuePair() *MetaDataKeyValuePair { + m := &MetaDataKeyValuePair{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateMetaDataKeyValuePairFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateMetaDataKeyValuePairFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewMetaDataKeyValuePair(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *MetaDataKeyValuePair) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *MetaDataKeyValuePair) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["key"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetKey(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateJsonFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetValue(val.(msmodel.Jsonable)) + } + return nil + } + return res +} + +// GetKey gets the key property value. Key of the metadata. +func (m *MetaDataKeyValuePair) GetKey() *string { + return m.key +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *MetaDataKeyValuePair) GetOdataType() *string { + return m.odataType +} + +// GetValue gets the value property value. Value of the metadata. Should be an object. +func (m *MetaDataKeyValuePair) GetValue() msmodel.Jsonable { + return m.value +} + +// Serialize serializes information the current object +func (m *MetaDataKeyValuePair) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteStringValue("key", m.GetKey()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteObjectValue("value", m.GetValue()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *MetaDataKeyValuePair) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetKey sets the key property value. Key of the metadata. +func (m *MetaDataKeyValuePair) SetKey(value *string) { + m.key = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *MetaDataKeyValuePair) SetOdataType(value *string) { + m.odataType = value +} + +// SetValue sets the value property value. Value of the metadata. Should be an object. +func (m *MetaDataKeyValuePair) SetValue(value msmodel.Jsonable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair_collection_response.go b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair_collection_response.go new file mode 100644 index 000000000..747cec59f --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// MetaDataKeyValuePairCollectionResponse +type MetaDataKeyValuePairCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []MetaDataKeyValuePairable +} + +// NewMetaDataKeyValuePairCollectionResponse instantiates a new MetaDataKeyValuePairCollectionResponse and sets the default values. +func NewMetaDataKeyValuePairCollectionResponse() *MetaDataKeyValuePairCollectionResponse { + m := &MetaDataKeyValuePairCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateMetaDataKeyValuePairCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateMetaDataKeyValuePairCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewMetaDataKeyValuePairCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *MetaDataKeyValuePairCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyValuePairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyValuePairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyValuePairable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *MetaDataKeyValuePairCollectionResponse) GetValue() []MetaDataKeyValuePairable { + return m.value +} + +// Serialize serializes information the current object +func (m *MetaDataKeyValuePairCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *MetaDataKeyValuePairCollectionResponse) SetValue(value []MetaDataKeyValuePairable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair_collection_responseable.go b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair_collection_responseable.go new file mode 100644 index 000000000..b2740c217 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pair_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// MetaDataKeyValuePairCollectionResponseable +type MetaDataKeyValuePairCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []MetaDataKeyValuePairable + SetValue(value []MetaDataKeyValuePairable) +} diff --git a/src/internal/connector/graph/betasdk/models/meta_data_key_value_pairable.go b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pairable.go new file mode 100644 index 000000000..e1bc31e74 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/meta_data_key_value_pairable.go @@ -0,0 +1,18 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// MetaDataKeyValuePairable +type MetaDataKeyValuePairable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetKey() *string + GetOdataType() *string + GetValue() msmodel.Jsonable + SetKey(value *string) + SetOdataType(value *string) + SetValue(value msmodel.Jsonable) +} diff --git a/src/internal/connector/graph/betasdk/models/page_layout_type.go b/src/internal/connector/graph/betasdk/models/page_layout_type.go new file mode 100644 index 000000000..fce795760 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/page_layout_type.go @@ -0,0 +1,42 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type PageLayoutType int + +const ( + MICROSOFTRESERVED_PAGELAYOUTTYPE PageLayoutType = iota + ARTICLE_PAGELAYOUTTYPE + HOME_PAGELAYOUTTYPE + UNKNOWNFUTUREVALUE_PAGELAYOUTTYPE +) + +func (i PageLayoutType) String() string { + return []string{"microsoftReserved", "article", "home", "unknownFutureValue"}[i] +} +func ParsePageLayoutType(v string) (interface{}, error) { + result := MICROSOFTRESERVED_PAGELAYOUTTYPE + switch v { + case "microsoftReserved": + result = MICROSOFTRESERVED_PAGELAYOUTTYPE + case "article": + result = ARTICLE_PAGELAYOUTTYPE + case "home": + result = HOME_PAGELAYOUTTYPE + case "unknownFutureValue": + result = UNKNOWNFUTUREVALUE_PAGELAYOUTTYPE + default: + return 0, errors.New("Unknown PageLayoutType value: " + v) + } + return &result, nil +} +func SerializePageLayoutType(values []PageLayoutType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/page_promotion_type.go b/src/internal/connector/graph/betasdk/models/page_promotion_type.go new file mode 100644 index 000000000..e78ce63f0 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/page_promotion_type.go @@ -0,0 +1,42 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type PagePromotionType int + +const ( + MICROSOFTRESERVED_PAGEPROMOTIONTYPE PagePromotionType = iota + PAGE_PAGEPROMOTIONTYPE + NEWSPOST_PAGEPROMOTIONTYPE + UNKNOWNFUTUREVALUE_PAGEPROMOTIONTYPE +) + +func (i PagePromotionType) String() string { + return []string{"microsoftReserved", "page", "newsPost", "unknownFutureValue"}[i] +} +func ParsePagePromotionType(v string) (interface{}, error) { + result := MICROSOFTRESERVED_PAGEPROMOTIONTYPE + switch v { + case "microsoftReserved": + result = MICROSOFTRESERVED_PAGEPROMOTIONTYPE + case "page": + result = PAGE_PAGEPROMOTIONTYPE + case "newsPost": + result = NEWSPOST_PAGEPROMOTIONTYPE + case "unknownFutureValue": + result = UNKNOWNFUTUREVALUE_PAGEPROMOTIONTYPE + default: + return 0, errors.New("Unknown PagePromotionType value: " + v) + } + return &result, nil +} +func SerializePagePromotionType(values []PagePromotionType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/publication_facet.go b/src/internal/connector/graph/betasdk/models/publication_facet.go new file mode 100644 index 000000000..860b88bf3 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/publication_facet.go @@ -0,0 +1,134 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// PublicationFacet +type PublicationFacet struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // The state of publication for this document. Either published or checkout. Read-only. + level *string + // The OdataType property + odataType *string + // The unique identifier for the version that is visible to the current caller. Read-only. + versionId *string +} + +// NewPublicationFacet instantiates a new publicationFacet and sets the default values. +func NewPublicationFacet() *PublicationFacet { + m := &PublicationFacet{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreatePublicationFacetFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreatePublicationFacetFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewPublicationFacet(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *PublicationFacet) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *PublicationFacet) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["level"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetLevel(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["versionId"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetVersionId(val) + } + return nil + } + return res +} + +// GetLevel gets the level property value. The state of publication for this document. Either published or checkout. Read-only. +func (m *PublicationFacet) GetLevel() *string { + return m.level +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *PublicationFacet) GetOdataType() *string { + return m.odataType +} + +// GetVersionId gets the versionId property value. The unique identifier for the version that is visible to the current caller. Read-only. +func (m *PublicationFacet) GetVersionId() *string { + return m.versionId +} + +// Serialize serializes information the current object +func (m *PublicationFacet) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteStringValue("level", m.GetLevel()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("versionId", m.GetVersionId()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *PublicationFacet) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetLevel sets the level property value. The state of publication for this document. Either published or checkout. Read-only. +func (m *PublicationFacet) SetLevel(value *string) { + m.level = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *PublicationFacet) SetOdataType(value *string) { + m.odataType = value +} + +// SetVersionId sets the versionId property value. The unique identifier for the version that is visible to the current caller. Read-only. +func (m *PublicationFacet) SetVersionId(value *string) { + m.versionId = value +} diff --git a/src/internal/connector/graph/betasdk/models/publication_facetable.go b/src/internal/connector/graph/betasdk/models/publication_facetable.go new file mode 100644 index 000000000..4098c89b1 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/publication_facetable.go @@ -0,0 +1,17 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// PublicationFacetable +type PublicationFacetable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetLevel() *string + GetOdataType() *string + GetVersionId() *string + SetLevel(value *string) + SetOdataType(value *string) + SetVersionId(value *string) +} diff --git a/src/internal/connector/graph/betasdk/models/reactions_facet.go b/src/internal/connector/graph/betasdk/models/reactions_facet.go new file mode 100644 index 000000000..c971925dc --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/reactions_facet.go @@ -0,0 +1,162 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// ReactionsFacet +type ReactionsFacet struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // Count of comments. + commentCount *int32 + // Count of likes. + likeCount *int32 + // The OdataType property + odataType *string + // Count of shares. + shareCount *int32 +} + +// NewReactionsFacet instantiates a new reactionsFacet and sets the default values. +func NewReactionsFacet() *ReactionsFacet { + m := &ReactionsFacet{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateReactionsFacetFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateReactionsFacetFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewReactionsFacet(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *ReactionsFacet) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetCommentCount gets the commentCount property value. Count of comments. +func (m *ReactionsFacet) GetCommentCount() *int32 { + return m.commentCount +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *ReactionsFacet) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["commentCount"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetInt32Value() + if err != nil { + return err + } + if val != nil { + m.SetCommentCount(val) + } + return nil + } + res["likeCount"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetInt32Value() + if err != nil { + return err + } + if val != nil { + m.SetLikeCount(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["shareCount"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetInt32Value() + if err != nil { + return err + } + if val != nil { + m.SetShareCount(val) + } + return nil + } + return res +} + +// GetLikeCount gets the likeCount property value. Count of likes. +func (m *ReactionsFacet) GetLikeCount() *int32 { + return m.likeCount +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *ReactionsFacet) GetOdataType() *string { + return m.odataType +} + +// GetShareCount gets the shareCount property value. Count of shares. +func (m *ReactionsFacet) GetShareCount() *int32 { + return m.shareCount +} + +// Serialize serializes information the current object +func (m *ReactionsFacet) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteInt32Value("commentCount", m.GetCommentCount()) + if err != nil { + return err + } + } + { + err := writer.WriteInt32Value("likeCount", m.GetLikeCount()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteInt32Value("shareCount", m.GetShareCount()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *ReactionsFacet) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetCommentCount sets the commentCount property value. Count of comments. +func (m *ReactionsFacet) SetCommentCount(value *int32) { + m.commentCount = value +} + +// SetLikeCount sets the likeCount property value. Count of likes. +func (m *ReactionsFacet) SetLikeCount(value *int32) { + m.likeCount = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *ReactionsFacet) SetOdataType(value *string) { + m.odataType = value +} + +// SetShareCount sets the shareCount property value. Count of shares. +func (m *ReactionsFacet) SetShareCount(value *int32) { + m.shareCount = value +} diff --git a/src/internal/connector/graph/betasdk/models/reactions_facetable.go b/src/internal/connector/graph/betasdk/models/reactions_facetable.go new file mode 100644 index 000000000..acdefec37 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/reactions_facetable.go @@ -0,0 +1,19 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// ReactionsFacetable +type ReactionsFacetable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetCommentCount() *int32 + GetLikeCount() *int32 + GetOdataType() *string + GetShareCount() *int32 + SetCommentCount(value *int32) + SetLikeCount(value *int32) + SetOdataType(value *string) + SetShareCount(value *int32) +} diff --git a/src/internal/connector/graph/betasdk/models/section_emphasis_type.go b/src/internal/connector/graph/betasdk/models/section_emphasis_type.go new file mode 100644 index 000000000..301ae839f --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/section_emphasis_type.go @@ -0,0 +1,45 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type SectionEmphasisType int + +const ( + NONE_SECTIONEMPHASISTYPE SectionEmphasisType = iota + NEUTRAL_SECTIONEMPHASISTYPE + SOFT_SECTIONEMPHASISTYPE + STRONG_SECTIONEMPHASISTYPE + UNKNOWNFUTUREVALUE_SECTIONEMPHASISTYPE +) + +func (i SectionEmphasisType) String() string { + return []string{"none", "neutral", "soft", "strong", "unknownFutureValue"}[i] +} +func ParseSectionEmphasisType(v string) (interface{}, error) { + result := NONE_SECTIONEMPHASISTYPE + switch v { + case "none": + result = NONE_SECTIONEMPHASISTYPE + case "neutral": + result = NEUTRAL_SECTIONEMPHASISTYPE + case "soft": + result = SOFT_SECTIONEMPHASISTYPE + case "strong": + result = STRONG_SECTIONEMPHASISTYPE + case "unknownFutureValue": + result = UNKNOWNFUTUREVALUE_SECTIONEMPHASISTYPE + default: + return 0, errors.New("Unknown SectionEmphasisType value: " + v) + } + return &result, nil +} +func SerializeSectionEmphasisType(values []SectionEmphasisType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/server_processed_content.go b/src/internal/connector/graph/betasdk/models/server_processed_content.go new file mode 100644 index 000000000..572a5f87a --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/server_processed_content.go @@ -0,0 +1,294 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// ServerProcessedContent +type ServerProcessedContent struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // A key-value map where keys are string identifiers and values are component ids. SharePoint servers might decide to use this hint to preload the script for corresponding components for performance boost. + componentDependencies []MetaDataKeyStringPairable + // A key-value map where keys are string identifier and values are object of custom key-value pair. + customMetadata []MetaDataKeyValuePairable + // A key-value map where keys are string identifiers and values are rich text with HTML format. SharePoint servers treat the values as HTML content and run services like safety checks, search index and link fixup on them. + htmlStrings []MetaDataKeyStringPairable + // A key-value map where keys are string identifiers and values are image sources. SharePoint servers treat the values as image sources and run services like search index and link fixup on them. + imageSources []MetaDataKeyStringPairable + // A key-value map where keys are string identifiers and values are links. SharePoint servers treat the values as links and run services like link fixup on them. + links []MetaDataKeyStringPairable + // The OdataType property + odataType *string + // A key-value map where keys are string identifiers and values are strings that should be search indexed. + searchablePlainTexts []MetaDataKeyStringPairable +} + +// NewServerProcessedContent instantiates a new serverProcessedContent and sets the default values. +func NewServerProcessedContent() *ServerProcessedContent { + m := &ServerProcessedContent{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateServerProcessedContentFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateServerProcessedContentFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewServerProcessedContent(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *ServerProcessedContent) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetComponentDependencies gets the componentDependencies property value. A key-value map where keys are string identifiers and values are component ids. SharePoint servers might decide to use this hint to preload the script for corresponding components for performance boost. +func (m *ServerProcessedContent) GetComponentDependencies() []MetaDataKeyStringPairable { + return m.componentDependencies +} + +// GetCustomMetadata gets the customMetadata property value. A key-value map where keys are string identifier and values are object of custom key-value pair. +func (m *ServerProcessedContent) GetCustomMetadata() []MetaDataKeyValuePairable { + return m.customMetadata +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *ServerProcessedContent) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["componentDependencies"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyStringPairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyStringPairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyStringPairable) + } + m.SetComponentDependencies(res) + } + return nil + } + res["customMetadata"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyValuePairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyValuePairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyValuePairable) + } + m.SetCustomMetadata(res) + } + return nil + } + res["htmlStrings"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyStringPairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyStringPairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyStringPairable) + } + m.SetHtmlStrings(res) + } + return nil + } + res["imageSources"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyStringPairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyStringPairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyStringPairable) + } + m.SetImageSources(res) + } + return nil + } + res["links"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyStringPairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyStringPairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyStringPairable) + } + m.SetLinks(res) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["searchablePlainTexts"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateMetaDataKeyStringPairFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]MetaDataKeyStringPairable, len(val)) + for i, v := range val { + res[i] = v.(MetaDataKeyStringPairable) + } + m.SetSearchablePlainTexts(res) + } + return nil + } + return res +} + +// GetHtmlStrings gets the htmlStrings property value. A key-value map where keys are string identifiers and values are rich text with HTML format. SharePoint servers treat the values as HTML content and run services like safety checks, search index and link fixup on them. +func (m *ServerProcessedContent) GetHtmlStrings() []MetaDataKeyStringPairable { + return m.htmlStrings +} + +// GetImageSources gets the imageSources property value. A key-value map where keys are string identifiers and values are image sources. SharePoint servers treat the values as image sources and run services like search index and link fixup on them. +func (m *ServerProcessedContent) GetImageSources() []MetaDataKeyStringPairable { + return m.imageSources +} + +// GetLinks gets the links property value. A key-value map where keys are string identifiers and values are links. SharePoint servers treat the values as links and run services like link fixup on them. +func (m *ServerProcessedContent) GetLinks() []MetaDataKeyStringPairable { + return m.links +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *ServerProcessedContent) GetOdataType() *string { + return m.odataType +} + +// GetSearchablePlainTexts gets the searchablePlainTexts property value. A key-value map where keys are string identifiers and values are strings that should be search indexed. +func (m *ServerProcessedContent) GetSearchablePlainTexts() []MetaDataKeyStringPairable { + return m.searchablePlainTexts +} + +// Serialize serializes information the current object +func (m *ServerProcessedContent) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + if m.GetComponentDependencies() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetComponentDependencies())) + for i, v := range m.GetComponentDependencies() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err := writer.WriteCollectionOfObjectValues("componentDependencies", cast) + if err != nil { + return err + } + } + if m.GetCustomMetadata() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetCustomMetadata())) + for i, v := range m.GetCustomMetadata() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err := writer.WriteCollectionOfObjectValues("customMetadata", cast) + if err != nil { + return err + } + } + if m.GetHtmlStrings() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetHtmlStrings())) + for i, v := range m.GetHtmlStrings() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err := writer.WriteCollectionOfObjectValues("htmlStrings", cast) + if err != nil { + return err + } + } + if m.GetImageSources() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetImageSources())) + for i, v := range m.GetImageSources() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err := writer.WriteCollectionOfObjectValues("imageSources", cast) + if err != nil { + return err + } + } + if m.GetLinks() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetLinks())) + for i, v := range m.GetLinks() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err := writer.WriteCollectionOfObjectValues("links", cast) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + if m.GetSearchablePlainTexts() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetSearchablePlainTexts())) + for i, v := range m.GetSearchablePlainTexts() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err := writer.WriteCollectionOfObjectValues("searchablePlainTexts", cast) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *ServerProcessedContent) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetComponentDependencies sets the componentDependencies property value. A key-value map where keys are string identifiers and values are component ids. SharePoint servers might decide to use this hint to preload the script for corresponding components for performance boost. +func (m *ServerProcessedContent) SetComponentDependencies(value []MetaDataKeyStringPairable) { + m.componentDependencies = value +} + +// SetCustomMetadata sets the customMetadata property value. A key-value map where keys are string identifier and values are object of custom key-value pair. +func (m *ServerProcessedContent) SetCustomMetadata(value []MetaDataKeyValuePairable) { + m.customMetadata = value +} + +// SetHtmlStrings sets the htmlStrings property value. A key-value map where keys are string identifiers and values are rich text with HTML format. SharePoint servers treat the values as HTML content and run services like safety checks, search index and link fixup on them. +func (m *ServerProcessedContent) SetHtmlStrings(value []MetaDataKeyStringPairable) { + m.htmlStrings = value +} + +// SetImageSources sets the imageSources property value. A key-value map where keys are string identifiers and values are image sources. SharePoint servers treat the values as image sources and run services like search index and link fixup on them. +func (m *ServerProcessedContent) SetImageSources(value []MetaDataKeyStringPairable) { + m.imageSources = value +} + +// SetLinks sets the links property value. A key-value map where keys are string identifiers and values are links. SharePoint servers treat the values as links and run services like link fixup on them. +func (m *ServerProcessedContent) SetLinks(value []MetaDataKeyStringPairable) { + m.links = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *ServerProcessedContent) SetOdataType(value *string) { + m.odataType = value +} + +// SetSearchablePlainTexts sets the searchablePlainTexts property value. A key-value map where keys are string identifiers and values are strings that should be search indexed. +func (m *ServerProcessedContent) SetSearchablePlainTexts(value []MetaDataKeyStringPairable) { + m.searchablePlainTexts = value +} diff --git a/src/internal/connector/graph/betasdk/models/server_processed_contentable.go b/src/internal/connector/graph/betasdk/models/server_processed_contentable.go new file mode 100644 index 000000000..5f9faed1a --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/server_processed_contentable.go @@ -0,0 +1,25 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// ServerProcessedContentable +type ServerProcessedContentable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetComponentDependencies() []MetaDataKeyStringPairable + GetCustomMetadata() []MetaDataKeyValuePairable + GetHtmlStrings() []MetaDataKeyStringPairable + GetImageSources() []MetaDataKeyStringPairable + GetLinks() []MetaDataKeyStringPairable + GetOdataType() *string + GetSearchablePlainTexts() []MetaDataKeyStringPairable + SetComponentDependencies(value []MetaDataKeyStringPairable) + SetCustomMetadata(value []MetaDataKeyValuePairable) + SetHtmlStrings(value []MetaDataKeyStringPairable) + SetImageSources(value []MetaDataKeyStringPairable) + SetLinks(value []MetaDataKeyStringPairable) + SetOdataType(value *string) + SetSearchablePlainTexts(value []MetaDataKeyStringPairable) +} diff --git a/src/internal/connector/graph/betasdk/models/site_access_type.go b/src/internal/connector/graph/betasdk/models/site_access_type.go new file mode 100644 index 000000000..2d4cedffe --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_access_type.go @@ -0,0 +1,39 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type SiteAccessType int + +const ( + BLOCK_SITEACCESSTYPE SiteAccessType = iota + FULL_SITEACCESSTYPE + LIMITED_SITEACCESSTYPE +) + +func (i SiteAccessType) String() string { + return []string{"block", "full", "limited"}[i] +} +func ParseSiteAccessType(v string) (interface{}, error) { + result := BLOCK_SITEACCESSTYPE + switch v { + case "block": + result = BLOCK_SITEACCESSTYPE + case "full": + result = FULL_SITEACCESSTYPE + case "limited": + result = LIMITED_SITEACCESSTYPE + default: + return 0, errors.New("Unknown SiteAccessType value: " + v) + } + return &result, nil +} +func SerializeSiteAccessType(values []SiteAccessType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/site_page.go b/src/internal/connector/graph/betasdk/models/site_page.go new file mode 100644 index 000000000..7555fed52 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_page.go @@ -0,0 +1,387 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// SitePage provides operations to call the remove method. +type SitePage struct { + BaseItem + // Indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section + canvasLayout CanvasLayoutable + // Inherited from baseItem. + contentType msmodel.ContentTypeInfoable + // The name of the page layout of the page. The possible values are: microsoftReserved, article, home, unknownFutureValue. + pageLayout *PageLayoutType + // Indicates the promotion kind of the sitePage. The possible values are: microsoftReserved, page, newsPost, unknownFutureValue. + promotionKind *PagePromotionType + // The publishing status and the MM.mm version of the page. + publishingState PublicationFacetable + // Reactions information for the page. + reactions ReactionsFacetable + // Determines whether or not to show comments at the bottom of the page. + showComments *bool + // Determines whether or not to show recommended pages at the bottom of the page. + showRecommendedPages *bool + // Url of the sitePage's thumbnail image + thumbnailWebUrl *string + // Title of the sitePage. + title *string + // Title area on the SharePoint page. + titleArea TitleAreaable + // Collection of webparts on the SharePoint page + webParts []WebPartable +} + +// NewSitePage instantiates a new sitePage and sets the default values. +func NewSitePage() *SitePage { + m := &SitePage{ + BaseItem: *NewBaseItem(), + } + odataTypeValue := "#microsoft.graph.sitePage" + m.SetOdataType(&odataTypeValue) + return m +} + +// CreateSitePageFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateSitePageFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewSitePage(), nil +} + +// GetCanvasLayout gets the canvasLayout property value. Indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section +func (m *SitePage) GetCanvasLayout() CanvasLayoutable { + return m.canvasLayout +} + +// GetContentType gets the contentType property value. Inherited from baseItem. +func (m *SitePage) GetContentType() msmodel.ContentTypeInfoable { + return m.contentType +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *SitePage) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseItem.GetFieldDeserializers() + res["canvasLayout"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateCanvasLayoutFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetCanvasLayout(val.(CanvasLayoutable)) + } + return nil + } + res["contentType"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateContentTypeInfoFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetContentType(val.(msmodel.ContentTypeInfoable)) + } + return nil + } + res["pageLayout"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParsePageLayoutType) + if err != nil { + return err + } + if val != nil { + m.SetPageLayout(val.(*PageLayoutType)) + } + return nil + } + res["promotionKind"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParsePagePromotionType) + if err != nil { + return err + } + if val != nil { + m.SetPromotionKind(val.(*PagePromotionType)) + } + return nil + } + res["publishingState"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreatePublicationFacetFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetPublishingState(val.(PublicationFacetable)) + } + return nil + } + res["reactions"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateReactionsFacetFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetReactions(val.(ReactionsFacetable)) + } + return nil + } + res["showComments"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetShowComments(val) + } + return nil + } + res["showRecommendedPages"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetShowRecommendedPages(val) + } + return nil + } + res["thumbnailWebUrl"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetThumbnailWebUrl(val) + } + return nil + } + res["title"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetTitle(val) + } + return nil + } + res["titleArea"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateTitleAreaFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetTitleArea(val.(TitleAreaable)) + } + return nil + } + res["webParts"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]WebPartable, len(val)) + for i, v := range val { + res[i] = v.(WebPartable) + } + m.SetWebParts(res) + } + return nil + } + return res +} + +// GetPageLayout gets the pageLayout property value. The name of the page layout of the page. The possible values are: microsoftReserved, article, home, unknownFutureValue. +func (m *SitePage) GetPageLayout() *PageLayoutType { + return m.pageLayout +} + +// GetPromotionKind gets the promotionKind property value. Indicates the promotion kind of the sitePage. The possible values are: microsoftReserved, page, newsPost, unknownFutureValue. +func (m *SitePage) GetPromotionKind() *PagePromotionType { + return m.promotionKind +} + +// GetPublishingState gets the publishingState property value. The publishing status and the MM.mm version of the page. +func (m *SitePage) GetPublishingState() PublicationFacetable { + return m.publishingState +} + +// GetReactions gets the reactions property value. Reactions information for the page. +func (m *SitePage) GetReactions() ReactionsFacetable { + return m.reactions +} + +// GetShowComments gets the showComments property value. Determines whether or not to show comments at the bottom of the page. +func (m *SitePage) GetShowComments() *bool { + return m.showComments +} + +// GetShowRecommendedPages gets the showRecommendedPages property value. Determines whether or not to show recommended pages at the bottom of the page. +func (m *SitePage) GetShowRecommendedPages() *bool { + return m.showRecommendedPages +} + +// GetThumbnailWebUrl gets the thumbnailWebUrl property value. Url of the sitePage's thumbnail image +func (m *SitePage) GetThumbnailWebUrl() *string { + return m.thumbnailWebUrl +} + +// GetTitle gets the title property value. Title of the sitePage. +func (m *SitePage) GetTitle() *string { + return m.title +} + +// GetTitleArea gets the titleArea property value. Title area on the SharePoint page. +func (m *SitePage) GetTitleArea() TitleAreaable { + return m.titleArea +} + +// GetWebParts gets the webParts property value. Collection of webparts on the SharePoint page +func (m *SitePage) GetWebParts() []WebPartable { + return m.webParts +} + +// Serialize serializes information the current object +func (m *SitePage) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseItem.Serialize(writer) + if err != nil { + return err + } + { + err = writer.WriteObjectValue("canvasLayout", m.GetCanvasLayout()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("contentType", m.GetContentType()) + if err != nil { + return err + } + } + if m.GetPageLayout() != nil { + cast := (*m.GetPageLayout()).String() + err = writer.WriteStringValue("pageLayout", &cast) + if err != nil { + return err + } + } + if m.GetPromotionKind() != nil { + cast := (*m.GetPromotionKind()).String() + err = writer.WriteStringValue("promotionKind", &cast) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("publishingState", m.GetPublishingState()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("reactions", m.GetReactions()) + if err != nil { + return err + } + } + { + err = writer.WriteBoolValue("showComments", m.GetShowComments()) + if err != nil { + return err + } + } + { + err = writer.WriteBoolValue("showRecommendedPages", m.GetShowRecommendedPages()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("thumbnailWebUrl", m.GetThumbnailWebUrl()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("title", m.GetTitle()) + if err != nil { + return err + } + } + { + err = writer.WriteObjectValue("titleArea", m.GetTitleArea()) + if err != nil { + return err + } + } + if m.GetWebParts() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetWebParts())) + for i, v := range m.GetWebParts() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("webParts", cast) + if err != nil { + return err + } + } + return nil +} + +// SetCanvasLayout sets the canvasLayout property value. Indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section +func (m *SitePage) SetCanvasLayout(value CanvasLayoutable) { + m.canvasLayout = value +} + +// SetContentType sets the contentType property value. Inherited from baseItem. +func (m *SitePage) SetContentType(value msmodel.ContentTypeInfoable) { + m.contentType = value +} + +// SetPageLayout sets the pageLayout property value. The name of the page layout of the page. The possible values are: microsoftReserved, article, home, unknownFutureValue. +func (m *SitePage) SetPageLayout(value *PageLayoutType) { + m.pageLayout = value +} + +// SetPromotionKind sets the promotionKind property value. Indicates the promotion kind of the sitePage. The possible values are: microsoftReserved, page, newsPost, unknownFutureValue. +func (m *SitePage) SetPromotionKind(value *PagePromotionType) { + m.promotionKind = value +} + +// SetPublishingState sets the publishingState property value. The publishing status and the MM.mm version of the page. +func (m *SitePage) SetPublishingState(value PublicationFacetable) { + m.publishingState = value +} + +// SetReactions sets the reactions property value. Reactions information for the page. +func (m *SitePage) SetReactions(value ReactionsFacetable) { + m.reactions = value +} + +// SetShowComments sets the showComments property value. Determines whether or not to show comments at the bottom of the page. +func (m *SitePage) SetShowComments(value *bool) { + m.showComments = value +} + +// SetShowRecommendedPages sets the showRecommendedPages property value. Determines whether or not to show recommended pages at the bottom of the page. +func (m *SitePage) SetShowRecommendedPages(value *bool) { + m.showRecommendedPages = value +} + +// SetThumbnailWebUrl sets the thumbnailWebUrl property value. Url of the sitePage's thumbnail image +func (m *SitePage) SetThumbnailWebUrl(value *string) { + m.thumbnailWebUrl = value +} + +// SetTitle sets the title property value. Title of the sitePage. +func (m *SitePage) SetTitle(value *string) { + m.title = value +} + +// SetTitleArea sets the titleArea property value. Title area on the SharePoint page. +func (m *SitePage) SetTitleArea(value TitleAreaable) { + m.titleArea = value +} + +// SetWebParts sets the webParts property value. Collection of webparts on the SharePoint page +func (m *SitePage) SetWebParts(value []WebPartable) { + m.webParts = value +} diff --git a/src/internal/connector/graph/betasdk/models/site_page_collection_response.go b/src/internal/connector/graph/betasdk/models/site_page_collection_response.go new file mode 100644 index 000000000..bbd79c3a4 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_page_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// SitePageCollectionResponse provides operations to manage the pages property of the microsoft.graph.site entity. +type SitePageCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []SitePageable +} + +// NewSitePageCollectionResponse instantiates a new SitePageCollectionResponse and sets the default values. +func NewSitePageCollectionResponse() *SitePageCollectionResponse { + m := &SitePageCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateSitePageCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateSitePageCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewSitePageCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *SitePageCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateSitePageFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]SitePageable, len(val)) + for i, v := range val { + res[i] = v.(SitePageable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *SitePageCollectionResponse) GetValue() []SitePageable { + return m.value +} + +// Serialize serializes information the current object +func (m *SitePageCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *SitePageCollectionResponse) SetValue(value []SitePageable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/site_page_collection_responseable.go b/src/internal/connector/graph/betasdk/models/site_page_collection_responseable.go new file mode 100644 index 000000000..30cceeb11 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_page_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// SitePageCollectionResponseable +type SitePageCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []SitePageable + SetValue(value []SitePageable) +} diff --git a/src/internal/connector/graph/betasdk/models/site_pageable.go b/src/internal/connector/graph/betasdk/models/site_pageable.go new file mode 100644 index 000000000..1131bfa9d --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_pageable.go @@ -0,0 +1,36 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// SitePageable +type SitePageable interface { + msmodel.BaseItemable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetCanvasLayout() CanvasLayoutable + GetContentType() msmodel.ContentTypeInfoable + GetPageLayout() *PageLayoutType + GetPromotionKind() *PagePromotionType + GetPublishingState() PublicationFacetable + GetReactions() ReactionsFacetable + GetShowComments() *bool + GetShowRecommendedPages() *bool + GetThumbnailWebUrl() *string + GetTitle() *string + GetTitleArea() TitleAreaable + GetWebParts() []WebPartable + SetCanvasLayout(value CanvasLayoutable) + SetContentType(value msmodel.ContentTypeInfoable) + SetPageLayout(value *PageLayoutType) + SetPromotionKind(value *PagePromotionType) + SetPublishingState(value PublicationFacetable) + SetReactions(value ReactionsFacetable) + SetShowComments(value *bool) + SetShowRecommendedPages(value *bool) + SetThumbnailWebUrl(value *string) + SetTitle(value *string) + SetTitleArea(value TitleAreaable) + SetWebParts(value []WebPartable) +} diff --git a/src/internal/connector/graph/betasdk/models/site_security_level.go b/src/internal/connector/graph/betasdk/models/site_security_level.go new file mode 100644 index 000000000..0c75c164e --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_security_level.go @@ -0,0 +1,54 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the add method. +type SiteSecurityLevel int + +const ( + // User Defined, default value, no intent. + USERDEFINED_SITESECURITYLEVEL SiteSecurityLevel = iota + // Low. + LOW_SITESECURITYLEVEL + // Medium-low. + MEDIUMLOW_SITESECURITYLEVEL + // Medium. + MEDIUM_SITESECURITYLEVEL + // Medium-high. + MEDIUMHIGH_SITESECURITYLEVEL + // High. + HIGH_SITESECURITYLEVEL +) + +func (i SiteSecurityLevel) String() string { + return []string{"userDefined", "low", "mediumLow", "medium", "mediumHigh", "high"}[i] +} +func ParseSiteSecurityLevel(v string) (interface{}, error) { + result := USERDEFINED_SITESECURITYLEVEL + switch v { + case "userDefined": + result = USERDEFINED_SITESECURITYLEVEL + case "low": + result = LOW_SITESECURITYLEVEL + case "mediumLow": + result = MEDIUMLOW_SITESECURITYLEVEL + case "medium": + result = MEDIUM_SITESECURITYLEVEL + case "mediumHigh": + result = MEDIUMHIGH_SITESECURITYLEVEL + case "high": + result = HIGH_SITESECURITYLEVEL + default: + return 0, errors.New("Unknown SiteSecurityLevel value: " + v) + } + return &result, nil +} +func SerializeSiteSecurityLevel(values []SiteSecurityLevel) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/site_settings.go b/src/internal/connector/graph/betasdk/models/site_settings.go new file mode 100644 index 000000000..1f8930408 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_settings.go @@ -0,0 +1,134 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// SiteSettings +type SiteSettings struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // The language tag for the language used on this site. + languageTag *string + // The OdataType property + odataType *string + // Indicates the time offset for the time zone of the site from Coordinated Universal Time (UTC). + timeZone *string +} + +// NewSiteSettings instantiates a new siteSettings and sets the default values. +func NewSiteSettings() *SiteSettings { + m := &SiteSettings{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateSiteSettingsFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateSiteSettingsFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewSiteSettings(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *SiteSettings) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *SiteSettings) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["languageTag"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetLanguageTag(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["timeZone"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetTimeZone(val) + } + return nil + } + return res +} + +// GetLanguageTag gets the languageTag property value. The language tag for the language used on this site. +func (m *SiteSettings) GetLanguageTag() *string { + return m.languageTag +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *SiteSettings) GetOdataType() *string { + return m.odataType +} + +// GetTimeZone gets the timeZone property value. Indicates the time offset for the time zone of the site from Coordinated Universal Time (UTC). +func (m *SiteSettings) GetTimeZone() *string { + return m.timeZone +} + +// Serialize serializes information the current object +func (m *SiteSettings) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteStringValue("languageTag", m.GetLanguageTag()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("timeZone", m.GetTimeZone()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *SiteSettings) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetLanguageTag sets the languageTag property value. The language tag for the language used on this site. +func (m *SiteSettings) SetLanguageTag(value *string) { + m.languageTag = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *SiteSettings) SetOdataType(value *string) { + m.odataType = value +} + +// SetTimeZone sets the timeZone property value. Indicates the time offset for the time zone of the site from Coordinated Universal Time (UTC). +func (m *SiteSettings) SetTimeZone(value *string) { + m.timeZone = value +} diff --git a/src/internal/connector/graph/betasdk/models/site_settingsable.go b/src/internal/connector/graph/betasdk/models/site_settingsable.go new file mode 100644 index 000000000..1b3825e05 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/site_settingsable.go @@ -0,0 +1,17 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// SiteSettingsable +type SiteSettingsable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetLanguageTag() *string + GetOdataType() *string + GetTimeZone() *string + SetLanguageTag(value *string) + SetOdataType(value *string) + SetTimeZone(value *string) +} diff --git a/src/internal/connector/graph/betasdk/models/standard_web_part.go b/src/internal/connector/graph/betasdk/models/standard_web_part.go new file mode 100644 index 000000000..4532e1d24 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/standard_web_part.go @@ -0,0 +1,96 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// StandardWebPart +type StandardWebPart struct { + WebPart + // Data of the webPart. + data WebPartDataable + // A Guid which indicates the type of the webParts + webPartType *string +} + +// NewStandardWebPart instantiates a new StandardWebPart and sets the default values. +func NewStandardWebPart() *StandardWebPart { + m := &StandardWebPart{ + WebPart: *NewWebPart(), + } + odataTypeValue := "#microsoft.graph.standardWebPart" + m.SetOdataType(&odataTypeValue) + return m +} + +// CreateStandardWebPartFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateStandardWebPartFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewStandardWebPart(), nil +} + +// GetData gets the data property value. Data of the webPart. +func (m *StandardWebPart) GetData() WebPartDataable { + return m.data +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *StandardWebPart) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.WebPart.GetFieldDeserializers() + res["data"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateWebPartDataFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetData(val.(WebPartDataable)) + } + return nil + } + res["webPartType"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetWebPartType(val) + } + return nil + } + return res +} + +// GetWebPartType gets the webPartType property value. A Guid which indicates the type of the webParts +func (m *StandardWebPart) GetWebPartType() *string { + return m.webPartType +} + +// Serialize serializes information the current object +func (m *StandardWebPart) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.WebPart.Serialize(writer) + if err != nil { + return err + } + { + err = writer.WriteObjectValue("data", m.GetData()) + if err != nil { + return err + } + } + { + err = writer.WriteStringValue("webPartType", m.GetWebPartType()) + if err != nil { + return err + } + } + return nil +} + +// SetData sets the data property value. Data of the webPart. +func (m *StandardWebPart) SetData(value WebPartDataable) { + m.data = value +} + +// SetWebPartType sets the webPartType property value. A Guid which indicates the type of the webParts +func (m *StandardWebPart) SetWebPartType(value *string) { + m.webPartType = value +} diff --git a/src/internal/connector/graph/betasdk/models/standard_web_part_collection_response.go b/src/internal/connector/graph/betasdk/models/standard_web_part_collection_response.go new file mode 100644 index 000000000..084496a8a --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/standard_web_part_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// StandardWebPartCollectionResponse +type StandardWebPartCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []StandardWebPartable +} + +// NewStandardWebPartCollectionResponse instantiates a new StandardWebPartCollectionResponse and sets the default values. +func NewStandardWebPartCollectionResponse() *StandardWebPartCollectionResponse { + m := &StandardWebPartCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateStandardWebPartCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateStandardWebPartCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewStandardWebPartCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *StandardWebPartCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateStandardWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]StandardWebPartable, len(val)) + for i, v := range val { + res[i] = v.(StandardWebPartable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *StandardWebPartCollectionResponse) GetValue() []StandardWebPartable { + return m.value +} + +// Serialize serializes information the current object +func (m *StandardWebPartCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *StandardWebPartCollectionResponse) SetValue(value []StandardWebPartable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/standard_web_part_collection_responseable.go b/src/internal/connector/graph/betasdk/models/standard_web_part_collection_responseable.go new file mode 100644 index 000000000..9e1f4d0d7 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/standard_web_part_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// StandardWebPartCollectionResponseable +type StandardWebPartCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []StandardWebPartable + SetValue(value []StandardWebPartable) +} diff --git a/src/internal/connector/graph/betasdk/models/standard_web_partable.go b/src/internal/connector/graph/betasdk/models/standard_web_partable.go new file mode 100644 index 000000000..b33c25f15 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/standard_web_partable.go @@ -0,0 +1,15 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// StandardWebPartable +type StandardWebPartable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + WebPartable + GetData() WebPartDataable + GetWebPartType() *string + SetData(value WebPartDataable) + SetWebPartType(value *string) +} diff --git a/src/internal/connector/graph/betasdk/models/text_web_part.go b/src/internal/connector/graph/betasdk/models/text_web_part.go new file mode 100644 index 000000000..1ae554671 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/text_web_part.go @@ -0,0 +1,68 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// TextWebPart +type TextWebPart struct { + WebPart + // The HTML string in text web part. + innerHtml *string +} + +// NewTextWebPart instantiates a new TextWebPart and sets the default values. +func NewTextWebPart() *TextWebPart { + m := &TextWebPart{ + WebPart: *NewWebPart(), + } + odataTypeValue := "#microsoft.graph.textWebPart" + m.SetOdataType(&odataTypeValue) + return m +} + +// CreateTextWebPartFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateTextWebPartFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewTextWebPart(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *TextWebPart) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.WebPart.GetFieldDeserializers() + res["innerHtml"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetInnerHtml(val) + } + return nil + } + return res +} + +// GetInnerHtml gets the innerHtml property value. The HTML string in text web part. +func (m *TextWebPart) GetInnerHtml() *string { + return m.innerHtml +} + +// Serialize serializes information the current object +func (m *TextWebPart) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.WebPart.Serialize(writer) + if err != nil { + return err + } + { + err = writer.WriteStringValue("innerHtml", m.GetInnerHtml()) + if err != nil { + return err + } + } + return nil +} + +// SetInnerHtml sets the innerHtml property value. The HTML string in text web part. +func (m *TextWebPart) SetInnerHtml(value *string) { + m.innerHtml = value +} diff --git a/src/internal/connector/graph/betasdk/models/text_web_part_collection_response.go b/src/internal/connector/graph/betasdk/models/text_web_part_collection_response.go new file mode 100644 index 000000000..ea07beae7 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/text_web_part_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// TextWebPartCollectionResponse +type TextWebPartCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []TextWebPartable +} + +// NewTextWebPartCollectionResponse instantiates a new TextWebPartCollectionResponse and sets the default values. +func NewTextWebPartCollectionResponse() *TextWebPartCollectionResponse { + m := &TextWebPartCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateTextWebPartCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateTextWebPartCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewTextWebPartCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *TextWebPartCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateTextWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]TextWebPartable, len(val)) + for i, v := range val { + res[i] = v.(TextWebPartable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *TextWebPartCollectionResponse) GetValue() []TextWebPartable { + return m.value +} + +// Serialize serializes information the current object +func (m *TextWebPartCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *TextWebPartCollectionResponse) SetValue(value []TextWebPartable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/text_web_part_collection_responseable.go b/src/internal/connector/graph/betasdk/models/text_web_part_collection_responseable.go new file mode 100644 index 000000000..785618756 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/text_web_part_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// TextWebPartCollectionResponseable +type TextWebPartCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []TextWebPartable + SetValue(value []TextWebPartable) +} diff --git a/src/internal/connector/graph/betasdk/models/text_web_partable.go b/src/internal/connector/graph/betasdk/models/text_web_partable.go new file mode 100644 index 000000000..f58b6a0c8 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/text_web_partable.go @@ -0,0 +1,13 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// TextWebPartable +type TextWebPartable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + WebPartable + GetInnerHtml() *string + SetInnerHtml(value *string) +} diff --git a/src/internal/connector/graph/betasdk/models/title_area.go b/src/internal/connector/graph/betasdk/models/title_area.go new file mode 100644 index 000000000..77b61ec7c --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/title_area.go @@ -0,0 +1,360 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// TitleArea +type TitleArea struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // Alternative text on the title area. + alternativeText *string + // Indicates whether the title area has a gradient effect enabled. + enableGradientEffect *bool + // URL of the image in the title area. + imageWebUrl *string + // Enumeration value that indicates the layout of the title area. The possible values are: imageAndTitle, plain, colorBlock, overlap, unknownFutureValue. + layout *TitleAreaLayoutType + // The OdataType property + odataType *string + // Contains collections of data that can be processed by server side services like search index and link fixup. + serverProcessedContent ServerProcessedContentable + // Indicates whether the author should be shown in title area. + showAuthor *bool + // Indicates whether the published date should be shown in title area. + showPublishedDate *bool + // Indicates whether the text block above title should be shown in title area. + showTextBlockAboveTitle *bool + // The text above title line. + textAboveTitle *string + // Enumeration value that indicates the text alignment of the title area. The possible values are: left, center, unknownFutureValue. + textAlignment *TitleAreaTextAlignmentType +} + +// NewTitleArea instantiates a new titleArea and sets the default values. +func NewTitleArea() *TitleArea { + m := &TitleArea{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateTitleAreaFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateTitleAreaFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewTitleArea(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *TitleArea) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetAlternativeText gets the alternativeText property value. Alternative text on the title area. +func (m *TitleArea) GetAlternativeText() *string { + return m.alternativeText +} + +// GetEnableGradientEffect gets the enableGradientEffect property value. Indicates whether the title area has a gradient effect enabled. +func (m *TitleArea) GetEnableGradientEffect() *bool { + return m.enableGradientEffect +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *TitleArea) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["alternativeText"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetAlternativeText(val) + } + return nil + } + res["enableGradientEffect"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetEnableGradientEffect(val) + } + return nil + } + res["imageWebUrl"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetImageWebUrl(val) + } + return nil + } + res["layout"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParseTitleAreaLayoutType) + if err != nil { + return err + } + if val != nil { + m.SetLayout(val.(*TitleAreaLayoutType)) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["serverProcessedContent"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateServerProcessedContentFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetServerProcessedContent(val.(ServerProcessedContentable)) + } + return nil + } + res["showAuthor"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetShowAuthor(val) + } + return nil + } + res["showPublishedDate"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetShowPublishedDate(val) + } + return nil + } + res["showTextBlockAboveTitle"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetShowTextBlockAboveTitle(val) + } + return nil + } + res["textAboveTitle"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetTextAboveTitle(val) + } + return nil + } + res["textAlignment"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParseTitleAreaTextAlignmentType) + if err != nil { + return err + } + if val != nil { + m.SetTextAlignment(val.(*TitleAreaTextAlignmentType)) + } + return nil + } + return res +} + +// GetImageWebUrl gets the imageWebUrl property value. URL of the image in the title area. +func (m *TitleArea) GetImageWebUrl() *string { + return m.imageWebUrl +} + +// GetLayout gets the layout property value. Enumeration value that indicates the layout of the title area. The possible values are: imageAndTitle, plain, colorBlock, overlap, unknownFutureValue. +func (m *TitleArea) GetLayout() *TitleAreaLayoutType { + return m.layout +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *TitleArea) GetOdataType() *string { + return m.odataType +} + +// GetServerProcessedContent gets the serverProcessedContent property value. Contains collections of data that can be processed by server side services like search index and link fixup. +func (m *TitleArea) GetServerProcessedContent() ServerProcessedContentable { + return m.serverProcessedContent +} + +// GetShowAuthor gets the showAuthor property value. Indicates whether the author should be shown in title area. +func (m *TitleArea) GetShowAuthor() *bool { + return m.showAuthor +} + +// GetShowPublishedDate gets the showPublishedDate property value. Indicates whether the published date should be shown in title area. +func (m *TitleArea) GetShowPublishedDate() *bool { + return m.showPublishedDate +} + +// GetShowTextBlockAboveTitle gets the showTextBlockAboveTitle property value. Indicates whether the text block above title should be shown in title area. +func (m *TitleArea) GetShowTextBlockAboveTitle() *bool { + return m.showTextBlockAboveTitle +} + +// GetTextAboveTitle gets the textAboveTitle property value. The text above title line. +func (m *TitleArea) GetTextAboveTitle() *string { + return m.textAboveTitle +} + +// GetTextAlignment gets the textAlignment property value. Enumeration value that indicates the text alignment of the title area. The possible values are: left, center, unknownFutureValue. +func (m *TitleArea) GetTextAlignment() *TitleAreaTextAlignmentType { + return m.textAlignment +} + +// Serialize serializes information the current object +func (m *TitleArea) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteStringValue("alternativeText", m.GetAlternativeText()) + if err != nil { + return err + } + } + { + err := writer.WriteBoolValue("enableGradientEffect", m.GetEnableGradientEffect()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("imageWebUrl", m.GetImageWebUrl()) + if err != nil { + return err + } + } + if m.GetLayout() != nil { + cast := (*m.GetLayout()).String() + err := writer.WriteStringValue("layout", &cast) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteObjectValue("serverProcessedContent", m.GetServerProcessedContent()) + if err != nil { + return err + } + } + { + err := writer.WriteBoolValue("showAuthor", m.GetShowAuthor()) + if err != nil { + return err + } + } + { + err := writer.WriteBoolValue("showPublishedDate", m.GetShowPublishedDate()) + if err != nil { + return err + } + } + { + err := writer.WriteBoolValue("showTextBlockAboveTitle", m.GetShowTextBlockAboveTitle()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("textAboveTitle", m.GetTextAboveTitle()) + if err != nil { + return err + } + } + if m.GetTextAlignment() != nil { + cast := (*m.GetTextAlignment()).String() + err := writer.WriteStringValue("textAlignment", &cast) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *TitleArea) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetAlternativeText sets the alternativeText property value. Alternative text on the title area. +func (m *TitleArea) SetAlternativeText(value *string) { + m.alternativeText = value +} + +// SetEnableGradientEffect sets the enableGradientEffect property value. Indicates whether the title area has a gradient effect enabled. +func (m *TitleArea) SetEnableGradientEffect(value *bool) { + m.enableGradientEffect = value +} + +// SetImageWebUrl sets the imageWebUrl property value. URL of the image in the title area. +func (m *TitleArea) SetImageWebUrl(value *string) { + m.imageWebUrl = value +} + +// SetLayout sets the layout property value. Enumeration value that indicates the layout of the title area. The possible values are: imageAndTitle, plain, colorBlock, overlap, unknownFutureValue. +func (m *TitleArea) SetLayout(value *TitleAreaLayoutType) { + m.layout = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *TitleArea) SetOdataType(value *string) { + m.odataType = value +} + +// SetServerProcessedContent sets the serverProcessedContent property value. Contains collections of data that can be processed by server side services like search index and link fixup. +func (m *TitleArea) SetServerProcessedContent(value ServerProcessedContentable) { + m.serverProcessedContent = value +} + +// SetShowAuthor sets the showAuthor property value. Indicates whether the author should be shown in title area. +func (m *TitleArea) SetShowAuthor(value *bool) { + m.showAuthor = value +} + +// SetShowPublishedDate sets the showPublishedDate property value. Indicates whether the published date should be shown in title area. +func (m *TitleArea) SetShowPublishedDate(value *bool) { + m.showPublishedDate = value +} + +// SetShowTextBlockAboveTitle sets the showTextBlockAboveTitle property value. Indicates whether the text block above title should be shown in title area. +func (m *TitleArea) SetShowTextBlockAboveTitle(value *bool) { + m.showTextBlockAboveTitle = value +} + +// SetTextAboveTitle sets the textAboveTitle property value. The text above title line. +func (m *TitleArea) SetTextAboveTitle(value *string) { + m.textAboveTitle = value +} + +// SetTextAlignment sets the textAlignment property value. Enumeration value that indicates the text alignment of the title area. The possible values are: left, center, unknownFutureValue. +func (m *TitleArea) SetTextAlignment(value *TitleAreaTextAlignmentType) { + m.textAlignment = value +} diff --git a/src/internal/connector/graph/betasdk/models/title_area_layout_type.go b/src/internal/connector/graph/betasdk/models/title_area_layout_type.go new file mode 100644 index 000000000..3621288a4 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/title_area_layout_type.go @@ -0,0 +1,45 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type TitleAreaLayoutType int + +const ( + IMAGEANDTITLE_TITLEAREALAYOUTTYPE TitleAreaLayoutType = iota + PLAIN_TITLEAREALAYOUTTYPE + COLORBLOCK_TITLEAREALAYOUTTYPE + OVERLAP_TITLEAREALAYOUTTYPE + UNKNOWNFUTUREVALUE_TITLEAREALAYOUTTYPE +) + +func (i TitleAreaLayoutType) String() string { + return []string{"imageAndTitle", "plain", "colorBlock", "overlap", "unknownFutureValue"}[i] +} +func ParseTitleAreaLayoutType(v string) (interface{}, error) { + result := IMAGEANDTITLE_TITLEAREALAYOUTTYPE + switch v { + case "imageAndTitle": + result = IMAGEANDTITLE_TITLEAREALAYOUTTYPE + case "plain": + result = PLAIN_TITLEAREALAYOUTTYPE + case "colorBlock": + result = COLORBLOCK_TITLEAREALAYOUTTYPE + case "overlap": + result = OVERLAP_TITLEAREALAYOUTTYPE + case "unknownFutureValue": + result = UNKNOWNFUTUREVALUE_TITLEAREALAYOUTTYPE + default: + return 0, errors.New("Unknown TitleAreaLayoutType value: " + v) + } + return &result, nil +} +func SerializeTitleAreaLayoutType(values []TitleAreaLayoutType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/title_area_text_alignment_type.go b/src/internal/connector/graph/betasdk/models/title_area_text_alignment_type.go new file mode 100644 index 000000000..a34f41dbe --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/title_area_text_alignment_type.go @@ -0,0 +1,39 @@ +package models + +import ( + "errors" +) + +// Provides operations to call the remove method. +type TitleAreaTextAlignmentType int + +const ( + LEFT_TITLEAREATEXTALIGNMENTTYPE TitleAreaTextAlignmentType = iota + CENTER_TITLEAREATEXTALIGNMENTTYPE + UNKNOWNFUTUREVALUE_TITLEAREATEXTALIGNMENTTYPE +) + +func (i TitleAreaTextAlignmentType) String() string { + return []string{"left", "center", "unknownFutureValue"}[i] +} +func ParseTitleAreaTextAlignmentType(v string) (interface{}, error) { + result := LEFT_TITLEAREATEXTALIGNMENTTYPE + switch v { + case "left": + result = LEFT_TITLEAREATEXTALIGNMENTTYPE + case "center": + result = CENTER_TITLEAREATEXTALIGNMENTTYPE + case "unknownFutureValue": + result = UNKNOWNFUTUREVALUE_TITLEAREATEXTALIGNMENTTYPE + default: + return 0, errors.New("Unknown TitleAreaTextAlignmentType value: " + v) + } + return &result, nil +} +func SerializeTitleAreaTextAlignmentType(values []TitleAreaTextAlignmentType) []string { + result := make([]string, len(values)) + for i, v := range values { + result[i] = v.String() + } + return result +} diff --git a/src/internal/connector/graph/betasdk/models/title_areaable.go b/src/internal/connector/graph/betasdk/models/title_areaable.go new file mode 100644 index 000000000..fb36bf576 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/title_areaable.go @@ -0,0 +1,33 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// TitleAreaable +type TitleAreaable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetAlternativeText() *string + GetEnableGradientEffect() *bool + GetImageWebUrl() *string + GetLayout() *TitleAreaLayoutType + GetOdataType() *string + GetServerProcessedContent() ServerProcessedContentable + GetShowAuthor() *bool + GetShowPublishedDate() *bool + GetShowTextBlockAboveTitle() *bool + GetTextAboveTitle() *string + GetTextAlignment() *TitleAreaTextAlignmentType + SetAlternativeText(value *string) + SetEnableGradientEffect(value *bool) + SetImageWebUrl(value *string) + SetLayout(value *TitleAreaLayoutType) + SetOdataType(value *string) + SetServerProcessedContent(value ServerProcessedContentable) + SetShowAuthor(value *bool) + SetShowPublishedDate(value *bool) + SetShowTextBlockAboveTitle(value *bool) + SetTextAboveTitle(value *string) + SetTextAlignment(value *TitleAreaTextAlignmentType) +} diff --git a/src/internal/connector/graph/betasdk/models/vertical_section.go b/src/internal/connector/graph/betasdk/models/vertical_section.go new file mode 100644 index 000000000..e4e8f6ed5 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/vertical_section.go @@ -0,0 +1,104 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// VerticalSection +type VerticalSection struct { + msmodel.Entity + // Enumeration value that indicates the emphasis of the section background. The possible values are: none, netural, soft, strong, unknownFutureValue. + emphasis *SectionEmphasisType + // The set of web parts in this section. + webparts []WebPartable +} + +// NewVerticalSection instantiates a new verticalSection and sets the default values. +func NewVerticalSection() *VerticalSection { + m := &VerticalSection{ + Entity: *msmodel.NewEntity(), + } + return m +} + +// CreateVerticalSectionFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateVerticalSectionFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewVerticalSection(), nil +} + +// GetEmphasis gets the emphasis property value. Enumeration value that indicates the emphasis of the section background. The possible values are: none, netural, soft, strong, unknownFutureValue. +func (m *VerticalSection) GetEmphasis() *SectionEmphasisType { + return m.emphasis +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *VerticalSection) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.Entity.GetFieldDeserializers() + res["emphasis"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetEnumValue(ParseSectionEmphasisType) + if err != nil { + return err + } + if val != nil { + m.SetEmphasis(val.(*SectionEmphasisType)) + } + return nil + } + res["webparts"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]WebPartable, len(val)) + for i, v := range val { + res[i] = v.(WebPartable) + } + m.SetWebparts(res) + } + return nil + } + return res +} + +// GetWebparts gets the webparts property value. The set of web parts in this section. +func (m *VerticalSection) GetWebparts() []WebPartable { + return m.webparts +} + +// Serialize serializes information the current object +func (m *VerticalSection) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.Entity.Serialize(writer) + if err != nil { + return err + } + if m.GetEmphasis() != nil { + cast := (*m.GetEmphasis()).String() + err = writer.WriteStringValue("emphasis", &cast) + if err != nil { + return err + } + } + if m.GetWebparts() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetWebparts())) + for i, v := range m.GetWebparts() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("webparts", cast) + if err != nil { + return err + } + } + return nil +} + +// SetEmphasis sets the emphasis property value. Enumeration value that indicates the emphasis of the section background. The possible values are: none, netural, soft, strong, unknownFutureValue. +func (m *VerticalSection) SetEmphasis(value *SectionEmphasisType) { + m.emphasis = value +} + +// SetWebparts sets the webparts property value. The set of web parts in this section. +func (m *VerticalSection) SetWebparts(value []WebPartable) { + m.webparts = value +} diff --git a/src/internal/connector/graph/betasdk/models/vertical_sectionable.go b/src/internal/connector/graph/betasdk/models/vertical_sectionable.go new file mode 100644 index 000000000..f4f0a991b --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/vertical_sectionable.go @@ -0,0 +1,16 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// VerticalSectionable +type VerticalSectionable interface { + msmodel.Entityable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetEmphasis() *SectionEmphasisType + GetWebparts() []WebPartable + SetEmphasis(value *SectionEmphasisType) + SetWebparts(value []WebPartable) +} diff --git a/src/internal/connector/graph/betasdk/models/web_part.go b/src/internal/connector/graph/betasdk/models/web_part.go new file mode 100644 index 000000000..3287051b1 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part.go @@ -0,0 +1,59 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// WebPart provides operations to call the remove method. +type WebPart struct { + msmodel.Entity +} + +// NewWebPart instantiates a new webPart and sets the default values. +func NewWebPart() *WebPart { + m := &WebPart{ + Entity: *msmodel.NewEntity(), + } + return m +} + +// CreateWebPartFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateWebPartFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + if parseNode != nil { + mappingValueNode, err := parseNode.GetChildNode("@odata.type") + if err != nil { + return nil, err + } + if mappingValueNode != nil { + mappingValue, err := mappingValueNode.GetStringValue() + if err != nil { + return nil, err + } + if mappingValue != nil { + switch *mappingValue { + case "#microsoft.graph.standardWebPart": + return NewStandardWebPart(), nil + case "#microsoft.graph.textWebPart": + return NewTextWebPart(), nil + } + } + } + } + return NewWebPart(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *WebPart) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.Entity.GetFieldDeserializers() + return res +} + +// Serialize serializes information the current object +func (m *WebPart) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.Entity.Serialize(writer) + if err != nil { + return err + } + return nil +} diff --git a/src/internal/connector/graph/betasdk/models/web_part_collection_response.go b/src/internal/connector/graph/betasdk/models/web_part_collection_response.go new file mode 100644 index 000000000..e590431b2 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part_collection_response.go @@ -0,0 +1,75 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// WebPartCollectionResponse provides operations to manage the webParts property of the microsoft.graph.sitePage entity. +type WebPartCollectionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []WebPartable +} + +// NewWebPartCollectionResponse instantiates a new WebPartCollectionResponse and sets the default values. +func NewWebPartCollectionResponse() *WebPartCollectionResponse { + m := &WebPartCollectionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateWebPartCollectionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateWebPartCollectionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewWebPartCollectionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *WebPartCollectionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(CreateWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]WebPartable, len(val)) + for i, v := range val { + res[i] = v.(WebPartable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +func (m *WebPartCollectionResponse) GetValue() []WebPartable { + return m.value +} + +// Serialize serializes information the current object +func (m *WebPartCollectionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +func (m *WebPartCollectionResponse) SetValue(value []WebPartable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/models/web_part_collection_responseable.go b/src/internal/connector/graph/betasdk/models/web_part_collection_responseable.go new file mode 100644 index 000000000..63aa0cae2 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part_collection_responseable.go @@ -0,0 +1,14 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// WebPartCollectionResponseable +type WebPartCollectionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []WebPartable + SetValue(value []WebPartable) +} diff --git a/src/internal/connector/graph/betasdk/models/web_part_data.go b/src/internal/connector/graph/betasdk/models/web_part_data.go new file mode 100644 index 000000000..251ed2dc9 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part_data.go @@ -0,0 +1,251 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// WebPartData +type WebPartData struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // Audience information of the web part. By using this property, specific content will be prioritized to specific audiences. + audiences []string + // Data version of the web part. The value is defined by the web part developer. Different dataVersions usually refers to a different property structure. + dataVersion *string + // Description of the web part. + description *string + // The OdataType property + odataType *string + // Properties bag of the web part. + properties msmodel.Jsonable + // Contains collections of data that can be processed by server side services like search index and link fixup. + serverProcessedContent ServerProcessedContentable + // Title of the web part. + title *string +} + +// NewWebPartData instantiates a new webPartData and sets the default values. +func NewWebPartData() *WebPartData { + m := &WebPartData{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateWebPartDataFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateWebPartDataFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewWebPartData(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *WebPartData) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetAudiences gets the audiences property value. Audience information of the web part. By using this property, specific content will be prioritized to specific audiences. +func (m *WebPartData) GetAudiences() []string { + return m.audiences +} + +// GetDataVersion gets the dataVersion property value. Data version of the web part. The value is defined by the web part developer. Different dataVersions usually refers to a different property structure. +func (m *WebPartData) GetDataVersion() *string { + return m.dataVersion +} + +// GetDescription gets the description property value. Description of the web part. +func (m *WebPartData) GetDescription() *string { + return m.description +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *WebPartData) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["audiences"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfPrimitiveValues("string") + if err != nil { + return err + } + if val != nil { + res := make([]string, len(val)) + for i, v := range val { + res[i] = *(v.(*string)) + } + m.SetAudiences(res) + } + return nil + } + res["dataVersion"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetDataVersion(val) + } + return nil + } + res["description"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetDescription(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["properties"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(msmodel.CreateJsonFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetProperties(val.(msmodel.Jsonable)) + } + return nil + } + res["serverProcessedContent"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetObjectValue(CreateServerProcessedContentFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + m.SetServerProcessedContent(val.(ServerProcessedContentable)) + } + return nil + } + res["title"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetTitle(val) + } + return nil + } + return res +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *WebPartData) GetOdataType() *string { + return m.odataType +} + +// GetProperties gets the properties property value. Properties bag of the web part. +func (m *WebPartData) GetProperties() msmodel.Jsonable { + return m.properties +} + +// GetServerProcessedContent gets the serverProcessedContent property value. Contains collections of data that can be processed by server side services like search index and link fixup. +func (m *WebPartData) GetServerProcessedContent() ServerProcessedContentable { + return m.serverProcessedContent +} + +// GetTitle gets the title property value. Title of the web part. +func (m *WebPartData) GetTitle() *string { + return m.title +} + +// Serialize serializes information the current object +func (m *WebPartData) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + if m.GetAudiences() != nil { + err := writer.WriteCollectionOfStringValues("audiences", m.GetAudiences()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("dataVersion", m.GetDataVersion()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("description", m.GetDescription()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteObjectValue("properties", m.GetProperties()) + if err != nil { + return err + } + } + { + err := writer.WriteObjectValue("serverProcessedContent", m.GetServerProcessedContent()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("title", m.GetTitle()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *WebPartData) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetAudiences sets the audiences property value. Audience information of the web part. By using this property, specific content will be prioritized to specific audiences. +func (m *WebPartData) SetAudiences(value []string) { + m.audiences = value +} + +// SetDataVersion sets the dataVersion property value. Data version of the web part. The value is defined by the web part developer. Different dataVersions usually refers to a different property structure. +func (m *WebPartData) SetDataVersion(value *string) { + m.dataVersion = value +} + +// SetDescription sets the description property value. Description of the web part. +func (m *WebPartData) SetDescription(value *string) { + m.description = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *WebPartData) SetOdataType(value *string) { + m.odataType = value +} + +// SetProperties sets the properties property value. Properties bag of the web part. +func (m *WebPartData) SetProperties(value msmodel.Jsonable) { + m.properties = value +} + +// SetServerProcessedContent sets the serverProcessedContent property value. Contains collections of data that can be processed by server side services like search index and link fixup. +func (m *WebPartData) SetServerProcessedContent(value ServerProcessedContentable) { + m.serverProcessedContent = value +} + +// SetTitle sets the title property value. Title of the web part. +func (m *WebPartData) SetTitle(value *string) { + m.title = value +} diff --git a/src/internal/connector/graph/betasdk/models/web_part_dataable.go b/src/internal/connector/graph/betasdk/models/web_part_dataable.go new file mode 100644 index 000000000..a27a6d158 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part_dataable.go @@ -0,0 +1,26 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// WebPartDataable +type WebPartDataable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetAudiences() []string + GetDataVersion() *string + GetDescription() *string + GetOdataType() *string + GetProperties() msmodel.Jsonable + GetServerProcessedContent() ServerProcessedContentable + GetTitle() *string + SetAudiences(value []string) + SetDataVersion(value *string) + SetDescription(value *string) + SetOdataType(value *string) + SetProperties(value msmodel.Jsonable) + SetServerProcessedContent(value ServerProcessedContentable) + SetTitle(value *string) +} diff --git a/src/internal/connector/graph/betasdk/models/web_part_position.go b/src/internal/connector/graph/betasdk/models/web_part_position.go new file mode 100644 index 000000000..f3be0e651 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part_position.go @@ -0,0 +1,190 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// WebPartPosition +type WebPartPosition struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // Indicates the identifier of the column where the web part is located. + columnId *float64 + // Indicates the horizontal section where the web part is located. + horizontalSectionId *float64 + // Indicates whether the web part is located in the vertical section. + isInVerticalSection *bool + // The OdataType property + odataType *string + // Index of the current web part. Represents the order of the web part in this column or section. + webPartIndex *float64 +} + +// NewWebPartPosition instantiates a new webPartPosition and sets the default values. +func NewWebPartPosition() *WebPartPosition { + m := &WebPartPosition{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateWebPartPositionFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +func CreateWebPartPositionFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewWebPartPosition(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *WebPartPosition) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetColumnId gets the columnId property value. Indicates the identifier of the column where the web part is located. +func (m *WebPartPosition) GetColumnId() *float64 { + return m.columnId +} + +// GetFieldDeserializers the deserialization information for the current model +func (m *WebPartPosition) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["columnId"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetFloat64Value() + if err != nil { + return err + } + if val != nil { + m.SetColumnId(val) + } + return nil + } + res["horizontalSectionId"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetFloat64Value() + if err != nil { + return err + } + if val != nil { + m.SetHorizontalSectionId(val) + } + return nil + } + res["isInVerticalSection"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetIsInVerticalSection(val) + } + return nil + } + res["@odata.type"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetStringValue() + if err != nil { + return err + } + if val != nil { + m.SetOdataType(val) + } + return nil + } + res["webPartIndex"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetFloat64Value() + if err != nil { + return err + } + if val != nil { + m.SetWebPartIndex(val) + } + return nil + } + return res +} + +// GetHorizontalSectionId gets the horizontalSectionId property value. Indicates the horizontal section where the web part is located. +func (m *WebPartPosition) GetHorizontalSectionId() *float64 { + return m.horizontalSectionId +} + +// GetIsInVerticalSection gets the isInVerticalSection property value. Indicates whether the web part is located in the vertical section. +func (m *WebPartPosition) GetIsInVerticalSection() *bool { + return m.isInVerticalSection +} + +// GetOdataType gets the @odata.type property value. The OdataType property +func (m *WebPartPosition) GetOdataType() *string { + return m.odataType +} + +// GetWebPartIndex gets the webPartIndex property value. Index of the current web part. Represents the order of the web part in this column or section. +func (m *WebPartPosition) GetWebPartIndex() *float64 { + return m.webPartIndex +} + +// Serialize serializes information the current object +func (m *WebPartPosition) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteFloat64Value("columnId", m.GetColumnId()) + if err != nil { + return err + } + } + { + err := writer.WriteFloat64Value("horizontalSectionId", m.GetHorizontalSectionId()) + if err != nil { + return err + } + } + { + err := writer.WriteBoolValue("isInVerticalSection", m.GetIsInVerticalSection()) + if err != nil { + return err + } + } + { + err := writer.WriteStringValue("@odata.type", m.GetOdataType()) + if err != nil { + return err + } + } + { + err := writer.WriteFloat64Value("webPartIndex", m.GetWebPartIndex()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +func (m *WebPartPosition) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetColumnId sets the columnId property value. Indicates the identifier of the column where the web part is located. +func (m *WebPartPosition) SetColumnId(value *float64) { + m.columnId = value +} + +// SetHorizontalSectionId sets the horizontalSectionId property value. Indicates the horizontal section where the web part is located. +func (m *WebPartPosition) SetHorizontalSectionId(value *float64) { + m.horizontalSectionId = value +} + +// SetIsInVerticalSection sets the isInVerticalSection property value. Indicates whether the web part is located in the vertical section. +func (m *WebPartPosition) SetIsInVerticalSection(value *bool) { + m.isInVerticalSection = value +} + +// SetOdataType sets the @odata.type property value. The OdataType property +func (m *WebPartPosition) SetOdataType(value *string) { + m.odataType = value +} + +// SetWebPartIndex sets the webPartIndex property value. Index of the current web part. Represents the order of the web part in this column or section. +func (m *WebPartPosition) SetWebPartIndex(value *float64) { + m.webPartIndex = value +} diff --git a/src/internal/connector/graph/betasdk/models/web_part_positionable.go b/src/internal/connector/graph/betasdk/models/web_part_positionable.go new file mode 100644 index 000000000..9655ac285 --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_part_positionable.go @@ -0,0 +1,21 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" +) + +// WebPartPositionable +type WebPartPositionable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetColumnId() *float64 + GetHorizontalSectionId() *float64 + GetIsInVerticalSection() *bool + GetOdataType() *string + GetWebPartIndex() *float64 + SetColumnId(value *float64) + SetHorizontalSectionId(value *float64) + SetIsInVerticalSection(value *bool) + SetOdataType(value *string) + SetWebPartIndex(value *float64) +} diff --git a/src/internal/connector/graph/betasdk/models/web_partable.go b/src/internal/connector/graph/betasdk/models/web_partable.go new file mode 100644 index 000000000..ac8a2a84d --- /dev/null +++ b/src/internal/connector/graph/betasdk/models/web_partable.go @@ -0,0 +1,12 @@ +package models + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" +) + +// WebPartable +type WebPartable interface { + msmodel.Entityable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable +} diff --git a/src/internal/connector/graph/betasdk/sites/count_request_builder.go b/src/internal/connector/graph/betasdk/sites/count_request_builder.go new file mode 100644 index 000000000..f36f1c220 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/count_request_builder.go @@ -0,0 +1,116 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// CountRequestBuilder provides operations to count the resources in the collection. +type CountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// CountRequestBuilderGetQueryParameters get the number of the resource +type CountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// CountRequestBuilderGetRequestConfiguration configuration for the request such as headers, +// query parameters, and middleware options. +type CountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *CountRequestBuilderGetQueryParameters +} + +// NewCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +func NewCountRequestBuilderInternal( + pathParameters map[string]string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *CountRequestBuilder { + m := &CountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +func NewCountRequestBuilder( + rawURL string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *CountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawURL + + return NewCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +func (m *CountRequestBuilder) CreateGetRequestInformation( + ctx context.Context, + requestConfiguration *CountRequestBuilderGetRequestConfiguration, +) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:lll +func (m *CountRequestBuilder) Get(ctx context.Context, requestConfiguration *CountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_count_request_builder.go new file mode 100644 index 000000000..284366a30 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_count_request_builder.go @@ -0,0 +1,115 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesCountRequestBuilder provides operations to count the resources in the collection. +type ItemPagesCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesCountRequestBuilderGetQueryParameters get the number of the resource +type ItemPagesCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemPagesCountRequestBuilderGetRequestConfiguration configuration for the request +// such as headers, query parameters, and middleware options. +type ItemPagesCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesCountRequestBuilderGetQueryParameters +} + +// NewItemPagesCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +func NewItemPagesCountRequestBuilderInternal( + pathParameters map[string]string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *ItemPagesCountRequestBuilder { + m := &ItemPagesCountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewItemPagesCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +func NewItemPagesCountRequestBuilder( + rawURL string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *ItemPagesCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawURL + + return NewItemPagesCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +// +//nolint:lll +func (m *ItemPagesCountRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesCountRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:lll +func (m *ItemPagesCountRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesCountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_count_request_builder.go new file mode 100644 index 000000000..deec0ca5f --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_count_request_builder.go @@ -0,0 +1,122 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder provides +// operations to count the resources in the collection. +type ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetQueryParameters get the number of the resource +type ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetRequestConfiguration configuration for +// the request such as headers, query parameters, and middleware options. +type ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetQueryParameters +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderInternal instantiates a +// new CountRequestBuilder and sets the default values. +func NewItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderInternal( + pathParameters map[string]string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder{} + //nolint:lll + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder instantiates a +// new CountRequestBuilder and sets the default values. +func NewItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder( + rawURL string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawURL + + return NewItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder) CreateGetRequestInformation( + ctx context.Context, + requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetRequestConfiguration, +) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error, +) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Get get the number of the resource +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder) Get( + ctx context.Context, + requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderGetRequestConfiguration, +) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_horizontal_section_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_horizontal_section_item_request_builder.go new file mode 100644 index 000000000..0845ecee4 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_horizontal_section_item_request_builder.go @@ -0,0 +1,260 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder +// provides operations to manage the horizontalSections property of the microsoft.graph.canvasLayout entity. +type ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderDeleteRequestConfiguration +// configuration for the request such as headers, query parameters, and middleware options. +type ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetQueryParameters +// collection of horizontal sections on the SharePoint page. +type ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetRequestConfiguration +// configuration for the request such as headers, query parameters, and middleware options. +type ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderPatchRequestConfiguration +// configuration for the request such as headers, query parameters, and middleware options. +type ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// Columns provides operations to manage the columns property of the microsoft.graph.horizontalSection entity. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) Columns() *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// ColumnsById provides operations to manage the columns property of the microsoft.graph.horizontalSection entity. +// +//nolint:revive +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) ColumnsById(id string, +) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + + if id != "" { + urlTplParams["horizontalSectionColumn%2Did"] = id + } + //nolint:lll + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderInternal +// instantiates a new HorizontalSectionItemRequestBuilder and sets the default values. +func NewItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderInternal( + pathParameters map[string]string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder{} + //nolint:lll + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder instantiates a +// new HorizontalSectionItemRequestBuilder and sets the default values. +func NewItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder( + rawURL string, + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter, +) *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawURL + + return NewItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderInternal( + urlParams, + requestAdapter, + ) +} + +// CreateDeleteRequestInformation delete navigation property horizontalSections for sites +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) CreateDeleteRequestInformation( + ctx context.Context, + requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderDeleteRequestConfiguration, +) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// CreateGetRequestInformation collection of horizontal sections on the SharePoint page. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) CreateGetRequestInformation( + ctx context.Context, + requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetRequestConfiguration, +) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property horizontalSections in sites +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + + err := requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if err != nil { + return nil, err + } + + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Delete delete navigation property horizontalSections for sites +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + + if err != nil { + return err + } + + return nil +} + +// Get collection of horizontal sections on the SharePoint page. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable), nil +} + +// Patch update the navigation property horizontalSections in sites +// nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_count_request_builder.go new file mode 100644 index 000000000..95a2e7314 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_count_request_builder.go @@ -0,0 +1,117 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder +// provides operations to count the resources in the collection. +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetQueryParameters get the number of the resource +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetQueryParameters +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:lll +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:lll +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder(rawURL string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawURL + + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_horizontal_section_column_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_horizontal_section_column_item_request_builder.go new file mode 100644 index 000000000..c1a8315ce --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_horizontal_section_column_item_request_builder.go @@ -0,0 +1,247 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder provides operations to manage the columns property of the microsoft.graph.horizontalSection entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetQueryParameters the set of vertical columns in this section. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderInternal instantiates a new HorizontalSectionColumnItemRequestBuilder and sets the default values. +// +//nolint:lll +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns/{horizontalSectionColumn%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder instantiates a new HorizontalSectionColumnItemRequestBuilder and sets the default values. +// +//nolint:lll, revive +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property columns for sites +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// CreateGetRequestInformation the set of vertical columns in this section. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property columns in sites +// +//nolint:lll,errcheck +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Delete delete navigation property columns for sites +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + + return nil +} + +// Get the set of vertical columns in this section. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionColumnFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable), nil +} + +// Patch update the navigation property columns in sites +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionColumnFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable), nil +} + +// Webparts provides operations to manage the webparts property of the microsoft.graph.horizontalSectionColumn entity. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) Webparts() *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// WebpartsById provides operations to manage the webparts property of the microsoft.graph.horizontalSectionColumn entity. +// +//nolint:lll,revive +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsHorizontalSectionColumnItemRequestBuilder) WebpartsById(id string) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + + if id != "" { + urlTplParams["webPart%2Did"] = id + } + + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_count_request_builder.go new file mode 100644 index 000000000..b5c6e3a40 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_count_request_builder.go @@ -0,0 +1,111 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder provides operations to count the resources in the collection. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetQueryParameters get the number of the resource +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetQueryParameters +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:lll +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns/{horizontalSectionColumn%2Did}/webparts/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:lll, revive +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_item_get_position_of_web_part_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_item_get_position_of_web_part_request_builder.go new file mode 100644 index 000000000..14429d80f --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_item_get_position_of_web_part_request_builder.go @@ -0,0 +1,96 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder provides operations to call the getPositionOfWebPart method. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderInternal instantiates a new GetPositionOfWebPartRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns/{horizontalSectionColumn%2Did}/webparts/{webPart%2Did}/microsoft.graph.getPositionOfWebPart" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder instantiates a new GetPositionOfWebPartRequestBuilder and sets the default values. +// +//nolint:lll,revive,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreatePostRequestInformation invoke action getPositionOfWebPart +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder) CreatePostRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// nolint:lll,wsl +// Post invoke action getPositionOfWebPart +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/webpart-getposition?view=graph-rest-1.0 +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder) Post(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartPositionable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartPositionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartPositionable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_request_builder.go new file mode 100644 index 000000000..4d2a94186 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_request_builder.go @@ -0,0 +1,180 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder provides operations to manage the webparts property of the microsoft.graph.horizontalSectionColumn entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetQueryParameters get the webPart resources from a sitePage. Sort by the order in which they appear on the page. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetQueryParameters struct { + // Include count of items + Count *bool `uriparametername:"%24count"` + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Order items by property values + Orderby []string `uriparametername:"%24orderby"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` + // Skip the first n items + Skip *int32 `uriparametername:"%24skip"` + // Show only the first n items + Top *int32 `uriparametername:"%24top"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderInternal instantiates a new WebpartsRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns/{horizontalSectionColumn%2Did}/webparts{?%24top,%24skip,%24search,%24filter,%24count,%24orderby,%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder instantiates a new WebpartsRequestBuilder and sets the default values. +// +//nolint:lll,revive,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderInternal(urlParams, requestAdapter) +} + +// Count provides operations to count the resources in the collection. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder) Count() *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsCountRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// CreateGetRequestInformation get the webPart resources from a sitePage. Sort by the order in which they appear on the page. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePostRequestInformation create new navigation property to webparts for sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get the webPart resources from a sitePage. Sort by the order in which they appear on the page. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/webpart-list?view=graph-rest-1.0 +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartCollectionResponseable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartCollectionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartCollectionResponseable), nil +} + +// Post create new navigation property to webparts for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilder) Post(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_web_part_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_web_part_item_request_builder.go new file mode 100644 index 000000000..0ce7becda --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_item_webparts_web_part_item_request_builder.go @@ -0,0 +1,209 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder provides operations to manage the webparts property of the microsoft.graph.horizontalSectionColumn entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetQueryParameters the collection of WebParts in this column. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderInternal instantiates a new WebPartItemRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns/{horizontalSectionColumn%2Did}/webparts/{webPart%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder instantiates a new WebPartItemRequestBuilder and sets the default values. +// +//nolint:lll,revive,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property webparts for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreateGetRequestInformation the collection of WebParts in this column. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property webparts in sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Delete delete navigation property webparts for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} + +// Get the collection of WebParts in this column. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} + +// GetPositionOfWebPart provides operations to call the getPositionOfWebPart method. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) GetPositionOfWebPart() *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsItemGetPositionOfWebPartRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// Patch update the navigation property webparts in sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsItemWebpartsWebPartItemRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_request_builder.go new file mode 100644 index 000000000..368738104 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_item_columns_request_builder.go @@ -0,0 +1,180 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder provides operations to manage the columns property of the microsoft.graph.horizontalSection entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetQueryParameters get a list of the horizontalSectionColumn objects and their properties. Sort by `id` in ascending order. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetQueryParameters struct { + // Include count of items + Count *bool `uriparametername:"%24count"` + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Order items by property values + Orderby []string `uriparametername:"%24orderby"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` + // Skip the first n items + Skip *int32 `uriparametername:"%24skip"` + // Show only the first n items + Top *int32 `uriparametername:"%24top"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderInternal instantiates a new ColumnsRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections/{horizontalSection%2Did}/columns{?%24top,%24skip,%24search,%24filter,%24count,%24orderby,%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder instantiates a new ColumnsRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderInternal(urlParams, requestAdapter) +} + +// Count provides operations to count the resources in the collection. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder) Count() *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsCountRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// CreateGetRequestInformation get a list of the horizontalSectionColumn objects and their properties. Sort by `id` in ascending order. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePostRequestInformation create new navigation property to columns for sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get a list of the horizontalSectionColumn objects and their properties. Sort by `id` in ascending order. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/horizontalsectioncolumn-list?view=graph-rest-1.0 +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnCollectionResponseable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionColumnCollectionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnCollectionResponseable), nil +} + +// Post create new navigation property to columns for sites +// +//nolint:lll, wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilder) Post(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsItemColumnsRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionColumnFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionColumnable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_request_builder.go new file mode 100644 index 000000000..829b830f0 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_horizontal_sections_request_builder.go @@ -0,0 +1,179 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder provides operations to manage the horizontalSections property of the microsoft.graph.canvasLayout entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetQueryParameters get a list of the horizontalSection objects and their properties. Sort by `id` in ascending order. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetQueryParameters struct { + // Include count of items + Count *bool `uriparametername:"%24count"` + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Order items by property values + Orderby []string `uriparametername:"%24orderby"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` + // Skip the first n items + Skip *int32 `uriparametername:"%24skip"` + // Show only the first n items + Top *int32 `uriparametername:"%24top"` +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderInternal instantiates a new HorizontalSectionsRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder { + m := &ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/horizontalSections{?%24top,%24skip,%24search,%24filter,%24count,%24orderby,%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder instantiates a new HorizontalSectionsRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderInternal(urlParams, requestAdapter) +} + +// Count provides operations to count the resources in the collection. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder) Count() *ItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsCountRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// CreateGetRequestInformation get a list of the horizontalSection objects and their properties. Sort by `id` in ascending order. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePostRequestInformation create new navigation property to horizontalSections for sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get a list of the horizontalSection objects and their properties. Sort by `id` in ascending order. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/horizontalsection-list?view=graph-rest-1.0 +// +//nolint:lll, wsl +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionCollectionResponseable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionCollectionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionCollectionResponseable), nil +} + +// nolint:lll,wsl +// Post create new navigation property to horizontalSections for sites +func (m *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder) Post(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, requestConfiguration *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateHorizontalSectionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.HorizontalSectionable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_request_builder.go new file mode 100644 index 000000000..bbca05a9b --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_request_builder.go @@ -0,0 +1,230 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutRequestBuilder provides operations to manage the canvasLayout property of the microsoft.graph.sitePage entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemCanvasLayoutRequestBuilderGetQueryParameters indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section +// +//nolint:lll +type ItemPagesItemCanvasLayoutRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemCanvasLayoutRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutRequestBuilderInternal instantiates a new CanvasLayoutRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutRequestBuilder { + m := &ItemPagesItemCanvasLayoutRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutRequestBuilder instantiates a new CanvasLayoutRequestBuilder and sets the default values. +// +//nolint:lll,revive,wsl +func NewItemPagesItemCanvasLayoutRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property canvasLayout for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreateGetRequestInformation indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property canvasLayout in sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CanvasLayoutable, requestConfiguration *ItemPagesItemCanvasLayoutRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Delete delete navigation property canvasLayout for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} + +// Get indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CanvasLayoutable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateCanvasLayoutFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CanvasLayoutable), nil +} + +// HorizontalSections provides operations to manage the horizontalSections property of the microsoft.graph.canvasLayout entity. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutRequestBuilder) HorizontalSections() *ItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilder { + return NewItemPagesItemCanvasLayoutHorizontalSectionsRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// HorizontalSectionsById provides operations to manage the horizontalSections property of the microsoft.graph.canvasLayout entity. +// +//nolint:lll,wsl,revive +func (m *ItemPagesItemCanvasLayoutRequestBuilder) HorizontalSectionsById(id string) *ItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + if id != "" { + urlTplParams["horizontalSection%2Did"] = id + } + return NewItemPagesItemCanvasLayoutHorizontalSectionsHorizontalSectionItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} + +// Patch update the navigation property canvasLayout in sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CanvasLayoutable, requestConfiguration *ItemPagesItemCanvasLayoutRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CanvasLayoutable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateCanvasLayoutFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CanvasLayoutable), nil +} + +// VerticalSection provides operations to manage the verticalSection property of the microsoft.graph.canvasLayout entity. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutRequestBuilder) VerticalSection() *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder { + return NewItemPagesItemCanvasLayoutVerticalSectionRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_request_builder.go new file mode 100644 index 000000000..3fbb916ca --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_request_builder.go @@ -0,0 +1,226 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder provides operations to manage the verticalSection property of the microsoft.graph.canvasLayout entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetQueryParameters read the properties and relationships of a verticalSection object. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutVerticalSectionRequestBuilderInternal instantiates a new VerticalSectionRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutVerticalSectionRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder { + m := &ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/verticalSection{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutVerticalSectionRequestBuilder instantiates a new VerticalSectionRequestBuilder and sets the default values. +// +//nolint:lll,revive,wsl +func NewItemPagesItemCanvasLayoutVerticalSectionRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutVerticalSectionRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property verticalSection for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreateGetRequestInformation read the properties and relationships of a verticalSection object. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property verticalSection in sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.VerticalSectionable, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Delete delete navigation property verticalSection for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} + +// Get read the properties and relationships of a verticalSection object. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/verticalsection-get?view=graph-rest-1.0 +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.VerticalSectionable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateVerticalSectionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.VerticalSectionable), nil +} + +// Patch update the navigation property verticalSection in sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.VerticalSectionable, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.VerticalSectionable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateVerticalSectionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.VerticalSectionable), nil +} + +// Webparts provides operations to manage the webparts property of the microsoft.graph.verticalSection entity. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) Webparts() *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder { + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// WebpartsById provides operations to manage the webparts property of the microsoft.graph.verticalSection entity. +// +//nolint:lll,wsl,revive +func (m *ItemPagesItemCanvasLayoutVerticalSectionRequestBuilder) WebpartsById(id string) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + if id != "" { + urlTplParams["webPart%2Did"] = id + } + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_count_request_builder.go new file mode 100644 index 000000000..774c55f28 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_count_request_builder.go @@ -0,0 +1,107 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder provides operations to count the resources in the collection. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetQueryParameters get the number of the resource +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetQueryParameters +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder { + m := &ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/verticalSection/webparts/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_item_get_position_of_web_part_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_item_get_position_of_web_part_request_builder.go new file mode 100644 index 000000000..d63ff729a --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_item_get_position_of_web_part_request_builder.go @@ -0,0 +1,97 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder provides operations to call the getPositionOfWebPart method. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderInternal instantiates a new GetPositionOfWebPartRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder { + m := &ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/verticalSection/webparts/{webPart%2Did}/microsoft.graph.getPositionOfWebPart" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder instantiates a new GetPositionOfWebPartRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreatePostRequestInformation invoke action getPositionOfWebPart +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder) CreatePostRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Post invoke action getPositionOfWebPart +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/webpart-getposition?view=graph-rest-1.0 +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder) Post(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartPositionable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartPositionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartPositionable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_request_builder.go new file mode 100644 index 000000000..bd1885be1 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_request_builder.go @@ -0,0 +1,177 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder provides operations to manage the webparts property of the microsoft.graph.verticalSection entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetQueryParameters the set of web parts in this section. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetQueryParameters struct { + // Include count of items + Count *bool `uriparametername:"%24count"` + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Order items by property values + Orderby []string `uriparametername:"%24orderby"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` + // Skip the first n items + Skip *int32 `uriparametername:"%24skip"` + // Show only the first n items + Top *int32 `uriparametername:"%24top"` +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderInternal instantiates a new WebpartsRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder { + m := &ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/verticalSection/webparts{?%24top,%24skip,%24search,%24filter,%24count,%24orderby,%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder instantiates a new WebpartsRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderInternal(urlParams, requestAdapter) +} + +// Count provides operations to count the resources in the collection. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder) Count() *ItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilder { + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsCountRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// CreateGetRequestInformation the set of web parts in this section. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePostRequestInformation create new navigation property to webparts for sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get the set of web parts in this section. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartCollectionResponseable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartCollectionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartCollectionResponseable), nil +} + +// Post create new navigation property to webparts for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilder) Post(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_web_part_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_web_part_item_request_builder.go new file mode 100644 index 000000000..fdb5025c5 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_canvas_layout_vertical_section_webparts_web_part_item_request_builder.go @@ -0,0 +1,209 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder provides operations to manage the webparts property of the microsoft.graph.verticalSection entity. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetQueryParameters the set of web parts in this section. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetQueryParameters +} + +// ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderInternal instantiates a new WebPartItemRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder { + m := &ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/canvasLayout/verticalSection/webparts/{webPart%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder instantiates a new WebPartItemRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property webparts for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreateGetRequestInformation the set of web parts in this section. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property webparts in sites +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Delete delete navigation property webparts for sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} + +// Get the set of web parts in this section. +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} + +// GetPositionOfWebPart provides operations to call the getPositionOfWebPart method. +// +//nolint:lll +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) GetPositionOfWebPart() *ItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilder { + return NewItemPagesItemCanvasLayoutVerticalSectionWebpartsItemGetPositionOfWebPartRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// Patch update the navigation property webparts in sites +// +//nolint:lll,wsl +func (m *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemCanvasLayoutVerticalSectionWebpartsWebPartItemRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_post_request_body.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_post_request_body.go new file mode 100644 index 000000000..5150584d8 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_post_request_body.go @@ -0,0 +1,182 @@ +package sites + +import i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + +// ItemPagesItemGetWebPartsByPositionPostRequestBody provides operations to call the getWebPartsByPosition method. +// +//nolint:lll,revive +type ItemPagesItemGetWebPartsByPositionPostRequestBody struct { + // Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + additionalData map[string]interface{} + // The columnId property + columnId *float64 + // The horizontalSectionId property + horizontalSectionId *float64 + // The isInVerticalSection property + isInVerticalSection *bool + // The webPartIndex property + webPartIndex *float64 +} + +// NewItemPagesItemGetWebPartsByPositionPostRequestBody instantiates a new ItemPagesItemGetWebPartsByPositionPostRequestBody and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemGetWebPartsByPositionPostRequestBody() *ItemPagesItemGetWebPartsByPositionPostRequestBody { + m := &ItemPagesItemGetWebPartsByPositionPostRequestBody{} + m.SetAdditionalData(make(map[string]interface{})) + return m +} + +// CreateItemPagesItemGetWebPartsByPositionPostRequestBodyFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +// +//nolint:lll +func CreateItemPagesItemGetWebPartsByPositionPostRequestBodyFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewItemPagesItemGetWebPartsByPositionPostRequestBody(), nil +} + +// GetAdditionalData gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +// +//nolint:lll +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) GetAdditionalData() map[string]interface{} { + return m.additionalData +} + +// GetColumnId gets the columnId property value. The columnId property +// +//nolint:lll,revive +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) GetColumnId() *float64 { + return m.columnId +} + +// GetFieldDeserializers the deserialization information for the current model +// +//nolint:lll,wsl,revive +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := make(map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error) + res["columnId"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetFloat64Value() + if err != nil { + return err + } + if val != nil { + m.SetColumnId(val) + } + return nil + } + res["horizontalSectionId"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetFloat64Value() + if err != nil { + return err + } + if val != nil { + m.SetHorizontalSectionId(val) + } + return nil + } + res["isInVerticalSection"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetBoolValue() + if err != nil { + return err + } + if val != nil { + m.SetIsInVerticalSection(val) + } + return nil + } + res["webPartIndex"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetFloat64Value() + if err != nil { + return err + } + if val != nil { + m.SetWebPartIndex(val) + } + return nil + } + return res +} + +// GetHorizontalSectionId gets the horizontalSectionId property value. The horizontalSectionId property +// +//nolint:lll,revive +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) GetHorizontalSectionId() *float64 { + return m.horizontalSectionId +} + +// GetIsInVerticalSection gets the isInVerticalSection property value. The isInVerticalSection property +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) GetIsInVerticalSection() *bool { + return m.isInVerticalSection +} + +// GetWebPartIndex gets the webPartIndex property value. The webPartIndex property +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) GetWebPartIndex() *float64 { + return m.webPartIndex +} + +// Serialize serializes information the current object +// +//nolint:lll,wsl +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + { + err := writer.WriteFloat64Value("columnId", m.GetColumnId()) + if err != nil { + return err + } + } + { + err := writer.WriteFloat64Value("horizontalSectionId", m.GetHorizontalSectionId()) + if err != nil { + return err + } + } + { + err := writer.WriteBoolValue("isInVerticalSection", m.GetIsInVerticalSection()) + if err != nil { + return err + } + } + { + err := writer.WriteFloat64Value("webPartIndex", m.GetWebPartIndex()) + if err != nil { + return err + } + } + { + err := writer.WriteAdditionalData(m.GetAdditionalData()) + if err != nil { + return err + } + } + return nil +} + +// SetAdditionalData sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. +// +//nolint:lll +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) SetAdditionalData(value map[string]interface{}) { + m.additionalData = value +} + +// SetColumnId sets the columnId property value. The columnId property +// +//nolint:lll,revive +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) SetColumnId(value *float64) { + m.columnId = value +} + +// SetHorizontalSectionId sets the horizontalSectionId property value. The horizontalSectionId property +// +//nolint:revive +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) SetHorizontalSectionId(value *float64) { + m.horizontalSectionId = value +} + +// SetIsInVerticalSection sets the isInVerticalSection property value. The isInVerticalSection property +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) SetIsInVerticalSection(value *bool) { + m.isInVerticalSection = value +} + +// SetWebPartIndex sets the webPartIndex property value. The webPartIndex property +func (m *ItemPagesItemGetWebPartsByPositionPostRequestBody) SetWebPartIndex(value *float64) { + m.webPartIndex = value +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_post_request_bodyable.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_post_request_bodyable.go new file mode 100644 index 000000000..9cad4e760 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_post_request_bodyable.go @@ -0,0 +1,17 @@ +package sites + +import i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + +// ItemPagesItemGetWebPartsByPositionPostRequestBodyable +type ItemPagesItemGetWebPartsByPositionPostRequestBodyable interface { + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.AdditionalDataHolder + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetColumnId() *float64 + GetHorizontalSectionId() *float64 + GetIsInVerticalSection() *bool + GetWebPartIndex() *float64 + SetColumnId(value *float64) + SetHorizontalSectionId(value *float64) + SetIsInVerticalSection(value *bool) + SetWebPartIndex(value *float64) +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_request_builder.go new file mode 100644 index 000000000..29ff2090b --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_request_builder.go @@ -0,0 +1,91 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemGetWebPartsByPositionRequestBuilder provides operations to call the getWebPartsByPosition method. +type ItemPagesItemGetWebPartsByPositionRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemGetWebPartsByPositionRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemGetWebPartsByPositionRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemGetWebPartsByPositionRequestBuilderInternal instantiates a new GetWebPartsByPositionRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemGetWebPartsByPositionRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemGetWebPartsByPositionRequestBuilder { + m := &ItemPagesItemGetWebPartsByPositionRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/microsoft.graph.getWebPartsByPosition" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemGetWebPartsByPositionRequestBuilder instantiates a new GetWebPartsByPositionRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemGetWebPartsByPositionRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemGetWebPartsByPositionRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemGetWebPartsByPositionRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreatePostRequestInformation invoke action getWebPartsByPosition +// +//nolint:lll,wsl,errcheck +func (m *ItemPagesItemGetWebPartsByPositionRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ItemPagesItemGetWebPartsByPositionPostRequestBodyable, requestConfiguration *ItemPagesItemGetWebPartsByPositionRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Post invoke action getWebPartsByPosition +// +//nolint:lll,wsl +func (m *ItemPagesItemGetWebPartsByPositionRequestBuilder) Post(ctx context.Context, body ItemPagesItemGetWebPartsByPositionPostRequestBodyable, requestConfiguration *ItemPagesItemGetWebPartsByPositionRequestBuilderPostRequestConfiguration) (ItemPagesItemGetWebPartsByPositionResponseable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, CreateItemPagesItemGetWebPartsByPositionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ItemPagesItemGetWebPartsByPositionResponseable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_response.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_response.go new file mode 100644 index 000000000..fa89d8855 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_response.go @@ -0,0 +1,89 @@ +package sites + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemGetWebPartsByPositionResponse provides operations to call the getWebPartsByPosition method. +type ItemPagesItemGetWebPartsByPositionResponse struct { + msmodel.BaseCollectionPaginationCountResponse + // The value property + value []ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable +} + +// NewItemPagesItemGetWebPartsByPositionResponse instantiates a new ItemPagesItemGetWebPartsByPositionResponse and sets the default values. +// +//nolint:wsl,lll +func NewItemPagesItemGetWebPartsByPositionResponse() *ItemPagesItemGetWebPartsByPositionResponse { + m := &ItemPagesItemGetWebPartsByPositionResponse{ + BaseCollectionPaginationCountResponse: *msmodel.NewBaseCollectionPaginationCountResponse(), + } + return m +} + +// CreateItemPagesItemGetWebPartsByPositionResponseFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value +// +//nolint:lll +func CreateItemPagesItemGetWebPartsByPositionResponseFromDiscriminatorValue(parseNode i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) (i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, error) { + return NewItemPagesItemGetWebPartsByPositionResponse(), nil +} + +// GetFieldDeserializers the deserialization information for the current model +// +//nolint:lll,wsl +func (m *ItemPagesItemGetWebPartsByPositionResponse) GetFieldDeserializers() map[string]func(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + res := m.BaseCollectionPaginationCountResponse.GetFieldDeserializers() + res["value"] = func(n i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.ParseNode) error { + val, err := n.GetCollectionOfObjectValues(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue) + if err != nil { + return err + } + if val != nil { + res := make([]ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, len(val)) + for i, v := range val { + res[i] = v.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable) + } + m.SetValue(res) + } + return nil + } + return res +} + +// GetValue gets the value property value. The value property +// +//nolint:lll +func (m *ItemPagesItemGetWebPartsByPositionResponse) GetValue() []ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable { + return m.value +} + +// Serialize serializes information the current object +// +//nolint:lll,wsl +func (m *ItemPagesItemGetWebPartsByPositionResponse) Serialize(writer i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.SerializationWriter) error { + err := m.BaseCollectionPaginationCountResponse.Serialize(writer) + if err != nil { + return err + } + if m.GetValue() != nil { + cast := make([]i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable, len(m.GetValue())) + for i, v := range m.GetValue() { + cast[i] = v.(i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable) + } + err = writer.WriteCollectionOfObjectValues("value", cast) + if err != nil { + return err + } + } + return nil +} + +// SetValue sets the value property value. The value property +// +//nolint:lll +func (m *ItemPagesItemGetWebPartsByPositionResponse) SetValue(value []ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable) { + m.value = value +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_responseable.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_responseable.go new file mode 100644 index 000000000..f862929ab --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_get_web_parts_by_position_responseable.go @@ -0,0 +1,16 @@ +package sites + +import ( + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91 "github.com/microsoft/kiota-abstractions-go/serialization" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemGetWebPartsByPositionResponseable +type ItemPagesItemGetWebPartsByPositionResponseable interface { + msmodel.BaseCollectionPaginationCountResponseable + i878a80d2330e89d26896388a3f487eef27b0a0e6c010c493bf80be1452208f91.Parsable + GetValue() []ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable + SetValue(value []ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable) +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_publish_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_publish_request_builder.go new file mode 100644 index 000000000..56197e940 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_publish_request_builder.go @@ -0,0 +1,82 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemPublishRequestBuilder provides operations to call the publish method. +type ItemPagesItemPublishRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// nolint:lll +// ItemPagesItemPublishRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +type ItemPagesItemPublishRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// nolint:lll,wsl +// NewItemPagesItemPublishRequestBuilderInternal instantiates a new PublishRequestBuilder and sets the default values. +func NewItemPagesItemPublishRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemPublishRequestBuilder { + m := &ItemPagesItemPublishRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/microsoft.graph.publish" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemPublishRequestBuilder instantiates a new PublishRequestBuilder and sets the default values. +// +//nolint:lll,wsl,revive +func NewItemPagesItemPublishRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemPublishRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemPublishRequestBuilderInternal(urlParams, requestAdapter) +} + +// //nolint:wsl,revive,lll +// CreatePostRequestInformation invoke action publish +func (m *ItemPagesItemPublishRequestBuilder) CreatePostRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemPublishRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// //nolint:wsl,revive,lll +// Post invoke action publish +func (m *ItemPagesItemPublishRequestBuilder) Post(ctx context.Context, requestConfiguration *ItemPagesItemPublishRequestBuilderPostRequestConfiguration) error { + requestInfo, err := m.CreatePostRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_count_request_builder.go new file mode 100644 index 000000000..57c875179 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_count_request_builder.go @@ -0,0 +1,103 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemPagesItemWebPartsCountRequestBuilder provides operations to count the resources in the collection. +type ItemPagesItemWebPartsCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemWebPartsCountRequestBuilderGetQueryParameters get the number of the resource +type ItemPagesItemWebPartsCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemPagesItemWebPartsCountRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemWebPartsCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemWebPartsCountRequestBuilderGetQueryParameters +} + +// NewItemPagesItemWebPartsCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsCountRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsCountRequestBuilder { + m := &ItemPagesItemWebPartsCountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/webParts/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemWebPartsCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsCountRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemWebPartsCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsCountRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsCountRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsCountRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsCountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_item_get_position_of_web_part_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_item_get_position_of_web_part_request_builder.go new file mode 100644 index 000000000..9db79ace5 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_item_get_position_of_web_part_request_builder.go @@ -0,0 +1,97 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder provides operations to call the getPositionOfWebPart method. +// +//nolint:lll +type ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderInternal instantiates a new GetPositionOfWebPartRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder { + m := &ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/webParts/{webPart%2Did}/microsoft.graph.getPositionOfWebPart" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder instantiates a new GetPositionOfWebPartRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreatePostRequestInformation invoke action getPositionOfWebPart +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder) CreatePostRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Post invoke action getPositionOfWebPart +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/webpart-getposition?view=graph-rest-1.0 +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder) Post(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartPositionable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartPositionFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartPositionable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_request_builder.go new file mode 100644 index 000000000..e2e32c640 --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_request_builder.go @@ -0,0 +1,173 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemWebPartsRequestBuilder provides operations to manage the webParts property of the microsoft.graph.sitePage entity. +// +//nolint:lll +type ItemPagesItemWebPartsRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemWebPartsRequestBuilderGetQueryParameters collection of webparts on the SharePoint page +type ItemPagesItemWebPartsRequestBuilderGetQueryParameters struct { + // Include count of items + Count *bool `uriparametername:"%24count"` + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Order items by property values + Orderby []string `uriparametername:"%24orderby"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` + // Skip the first n items + Skip *int32 `uriparametername:"%24skip"` + // Show only the first n items + Top *int32 `uriparametername:"%24top"` +} + +// ItemPagesItemWebPartsRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemWebPartsRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemWebPartsRequestBuilderGetQueryParameters +} + +// ItemPagesItemWebPartsRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesItemWebPartsRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemWebPartsRequestBuilderInternal instantiates a new WebPartsRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewItemPagesItemWebPartsRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsRequestBuilder { + m := &ItemPagesItemWebPartsRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/webParts{?%24top,%24skip,%24search,%24filter,%24count,%24orderby,%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemWebPartsRequestBuilder instantiates a new WebPartsRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemWebPartsRequestBuilderInternal(urlParams, requestAdapter) +} + +// Count provides operations to count the resources in the collection. +func (m *ItemPagesItemWebPartsRequestBuilder) Count() *ItemPagesItemWebPartsCountRequestBuilder { + return NewItemPagesItemWebPartsCountRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// CreateGetRequestInformation collection of webparts on the SharePoint page +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePostRequestInformation create new navigation property to webParts for sites +// +//nolint:wsl,revive,lll,errcheck +func (m *ItemPagesItemWebPartsRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemWebPartsRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get collection of webparts on the SharePoint page +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartCollectionResponseable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartCollectionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartCollectionResponseable), nil +} + +// Post create new navigation property to webParts for sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsRequestBuilder) Post(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemWebPartsRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_web_part_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_web_part_item_request_builder.go new file mode 100644 index 000000000..1c16fc8df --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_item_web_parts_web_part_item_request_builder.go @@ -0,0 +1,209 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesItemWebPartsWebPartItemRequestBuilder provides operations to manage the webParts property of the microsoft.graph.sitePage entity. +// +//nolint:wsl,revive,lll +type ItemPagesItemWebPartsWebPartItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesItemWebPartsWebPartItemRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:wsl,revive,lll +type ItemPagesItemWebPartsWebPartItemRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesItemWebPartsWebPartItemRequestBuilderGetQueryParameters collection of webparts on the SharePoint page +// +//nolint:wsl,revive,lll +type ItemPagesItemWebPartsWebPartItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesItemWebPartsWebPartItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:wsl,revive,lll +type ItemPagesItemWebPartsWebPartItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesItemWebPartsWebPartItemRequestBuilderGetQueryParameters +} + +// ItemPagesItemWebPartsWebPartItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:wsl,revive,lll +type ItemPagesItemWebPartsWebPartItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesItemWebPartsWebPartItemRequestBuilderInternal instantiates a new WebPartItemRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsWebPartItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsWebPartItemRequestBuilder { + m := &ItemPagesItemWebPartsWebPartItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}/webParts/{webPart%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesItemWebPartsWebPartItemRequestBuilder instantiates a new WebPartItemRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesItemWebPartsWebPartItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesItemWebPartsWebPartItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesItemWebPartsWebPartItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property webParts for sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsWebPartItemRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreateGetRequestInformation collection of webparts on the SharePoint page +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsWebPartItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property webParts in sites +// +//nolint:wsl,revive,lll,errcheck +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemWebPartsWebPartItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Delete delete navigation property webParts for sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsWebPartItemRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} + +// Get collection of webparts on the SharePoint page +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesItemWebPartsWebPartItemRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} + +// GetPositionOfWebPart provides operations to call the getPositionOfWebPart method. +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) GetPositionOfWebPart() *ItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilder { + return NewItemPagesItemWebPartsItemGetPositionOfWebPartRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// Patch update the navigation property webParts in sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesItemWebPartsWebPartItemRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, requestConfiguration *ItemPagesItemWebPartsWebPartItemRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateWebPartFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.WebPartable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_request_builder.go new file mode 100644 index 000000000..6c82f58df --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_request_builder.go @@ -0,0 +1,177 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesRequestBuilder provides operations to manage the pages property of the microsoft.graph.site entity. +type ItemPagesRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesRequestBuilderGetQueryParameters get the collection of [sitePage][] objects from the site pages [list][] in a site [site][]. All pages in the site are returned (with pagination). Sort alphabetically by `name` in ascending order. +// +//nolint:lll +type ItemPagesRequestBuilderGetQueryParameters struct { + // Include count of items + Count *bool `uriparametername:"%24count"` + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Order items by property values + Orderby []string `uriparametername:"%24orderby"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` + // Skip the first n items + Skip *int32 `uriparametername:"%24skip"` + // Show only the first n items + Top *int32 `uriparametername:"%24top"` +} + +// ItemPagesRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:wsl,revive,lll +type ItemPagesRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesRequestBuilderGetQueryParameters +} + +// ItemPagesRequestBuilderPostRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:wsl,revive,lll +type ItemPagesRequestBuilderPostRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// NewItemPagesRequestBuilderInternal instantiates a new PagesRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesRequestBuilder { + m := &ItemPagesRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages{?%24top,%24skip,%24search,%24filter,%24count,%24orderby,%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesRequestBuilder instantiates a new PagesRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesRequestBuilderInternal(urlParams, requestAdapter) +} + +// Count provides operations to count the resources in the collection. +func (m *ItemPagesRequestBuilder) Count() *ItemPagesCountRequestBuilder { + return NewItemPagesCountRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// CreateGetRequestInformation get the collection of [sitePage][] objects from the site pages [list][] in a site [site][]. All pages in the site are returned (with pagination). Sort alphabetically by `name` in ascending order. +// +//nolint:wsl,revive,lll +func (m *ItemPagesRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePostRequestInformation create a new [sitePage][] in the site pages [list][] in a [site][]. +// +//nolint:errcheck,lll,wsl +func (m *ItemPagesRequestBuilder) CreatePostRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, requestConfiguration *ItemPagesRequestBuilderPostRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.POST + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get the collection of [sitePage][] objects from the site pages [list][] in a site [site][]. All pages in the site are returned (with pagination). Sort alphabetically by `name` in ascending order. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/sitepage-list?view=graph-rest-1.0 +// //nolint:wsl,revive,lll +func (m *ItemPagesRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageCollectionResponseable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateSitePageCollectionResponseFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageCollectionResponseable), nil +} + +// Post create a new [sitePage][] in the site pages [list][] in a [site][]. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/sitepage-create?view=graph-rest-1.0 +// nolint:wsl,revive,lll +func (m *ItemPagesRequestBuilder) Post(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, requestConfiguration *ItemPagesRequestBuilderPostRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, error) { + requestInfo, err := m.CreatePostRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateSitePageFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_pages_site_page_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_pages_site_page_item_request_builder.go new file mode 100644 index 000000000..29fda72bd --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_pages_site_page_item_request_builder.go @@ -0,0 +1,237 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + + ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354 "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" +) + +// ItemPagesSitePageItemRequestBuilder provides operations to manage the pages property of the microsoft.graph.site entity. +// +//nolint:lll +type ItemPagesSitePageItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemPagesSitePageItemRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesSitePageItemRequestBuilderDeleteRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// ItemPagesSitePageItemRequestBuilderGetQueryParameters the collection of pages in the SitePages list in this site. +type ItemPagesSitePageItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemPagesSitePageItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemPagesSitePageItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemPagesSitePageItemRequestBuilderGetQueryParameters +} + +// ItemPagesSitePageItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:wsl,revive,lll +type ItemPagesSitePageItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// CanvasLayout provides operations to manage the canvasLayout property of the microsoft.graph.sitePage entity. +func (m *ItemPagesSitePageItemRequestBuilder) CanvasLayout() *ItemPagesItemCanvasLayoutRequestBuilder { + return NewItemPagesItemCanvasLayoutRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// NewItemPagesSitePageItemRequestBuilderInternal instantiates a new SitePageItemRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesSitePageItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesSitePageItemRequestBuilder { + m := &ItemPagesSitePageItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/pages/{sitePage%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemPagesSitePageItemRequestBuilder instantiates a new SitePageItemRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemPagesSitePageItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemPagesSitePageItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemPagesSitePageItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateDeleteRequestInformation delete navigation property pages for sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesSitePageItemRequestBuilder) CreateDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemPagesSitePageItemRequestBuilderDeleteRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreateGetRequestInformation the collection of pages in the SitePages list in this site. +// +//nolint:wsl,revive,lll +func (m *ItemPagesSitePageItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemPagesSitePageItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update the navigation property pages in sites +// +//nolint:errcheck,lll,wsl +func (m *ItemPagesSitePageItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, requestConfiguration *ItemPagesSitePageItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Delete delete navigation property pages for sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesSitePageItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemPagesSitePageItemRequestBuilderDeleteRequestConfiguration) error { + requestInfo, err := m.CreateDeleteRequestInformation(ctx, requestConfiguration) + if err != nil { + return err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + err = m.requestAdapter.SendNoContent(ctx, requestInfo, errorMapping) + if err != nil { + return err + } + return nil +} + +// Get the collection of pages in the SitePages list in this site. +// +//nolint:wsl,revive,lll +func (m *ItemPagesSitePageItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemPagesSitePageItemRequestBuilderGetRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateSitePageFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable), nil +} + +// GetWebPartsByPosition provides operations to call the getWebPartsByPosition method. +// +//nolint:wsl,revive,lll +func (m *ItemPagesSitePageItemRequestBuilder) GetWebPartsByPosition() *ItemPagesItemGetWebPartsByPositionRequestBuilder { + return NewItemPagesItemGetWebPartsByPositionRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// Patch update the navigation property pages in sites +// +//nolint:wsl,revive,lll +func (m *ItemPagesSitePageItemRequestBuilder) Patch(ctx context.Context, body ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, requestConfiguration *ItemPagesSitePageItemRequestBuilderPatchRequestConfiguration) (ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.CreateSitePageFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(ifda19816f54f079134d70c11e75d6b26799300cf72079e282f1d3bb9a6750354.SitePageable), nil +} + +// Publish provides operations to call the publish method. +func (m *ItemPagesSitePageItemRequestBuilder) Publish() *ItemPagesItemPublishRequestBuilder { + return NewItemPagesItemPublishRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// WebParts provides operations to manage the webParts property of the microsoft.graph.sitePage entity. +func (m *ItemPagesSitePageItemRequestBuilder) WebParts() *ItemPagesItemWebPartsRequestBuilder { + return NewItemPagesItemWebPartsRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// WebPartsById provides operations to manage the webParts property of the microsoft.graph.sitePage entity. +// +//nolint:revive,wsl +func (m *ItemPagesSitePageItemRequestBuilder) WebPartsById(id string) *ItemPagesItemWebPartsWebPartItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + if id != "" { + urlTplParams["webPart%2Did"] = id + } + return NewItemPagesItemWebPartsWebPartItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} diff --git a/src/internal/connector/graph/betasdk/sites/item_sites_count_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_sites_count_request_builder.go new file mode 100644 index 000000000..5a83c959c --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_sites_count_request_builder.go @@ -0,0 +1,103 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemSitesCountRequestBuilder provides operations to count the resources in the collection. +type ItemSitesCountRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemSitesCountRequestBuilderGetQueryParameters get the number of the resource +type ItemSitesCountRequestBuilderGetQueryParameters struct { + // Filter items by property values + Filter *string `uriparametername:"%24filter"` + // Search items by search phrases + Search *string `uriparametername:"%24search"` +} + +// ItemSitesCountRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemSitesCountRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemSitesCountRequestBuilderGetQueryParameters +} + +// NewItemSitesCountRequestBuilderInternal instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:wsl,lll +func NewItemSitesCountRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemSitesCountRequestBuilder { + m := &ItemSitesCountRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/sites/$count{?%24search,%24filter}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemSitesCountRequestBuilder instantiates a new CountRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemSitesCountRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemSitesCountRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemSitesCountRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation get the number of the resource +// +//nolint:wsl,revive,lll +func (m *ItemSitesCountRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemSitesCountRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "text/plain") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get get the number of the resource +// +//nolint:wsl,revive,lll +func (m *ItemSitesCountRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemSitesCountRequestBuilderGetRequestConfiguration) (*int32, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.SendPrimitive(ctx, requestInfo, "int32", errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*int32), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/item_sites_site_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/item_sites_site_item_request_builder.go new file mode 100644 index 000000000..c5959b0ff --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/item_sites_site_item_request_builder.go @@ -0,0 +1,104 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// ItemSitesSiteItemRequestBuilder provides operations to manage the sites property of the microsoft.graph.site entity. +type ItemSitesSiteItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// ItemSitesSiteItemRequestBuilderGetQueryParameters the collection of the sub-sites under this site. +type ItemSitesSiteItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// ItemSitesSiteItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type ItemSitesSiteItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *ItemSitesSiteItemRequestBuilderGetQueryParameters +} + +// NewItemSitesSiteItemRequestBuilderInternal instantiates a new SiteItemRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemSitesSiteItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemSitesSiteItemRequestBuilder { + m := &ItemSitesSiteItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}/sites/{site%2Did1}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewItemSitesSiteItemRequestBuilder instantiates a new SiteItemRequestBuilder and sets the default values. +// +//nolint:wsl,revive,lll +func NewItemSitesSiteItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *ItemSitesSiteItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewItemSitesSiteItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// CreateGetRequestInformation the collection of the sub-sites under this site. +// +//nolint:wsl,revive,lll +func (m *ItemSitesSiteItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *ItemSitesSiteItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// Get the collection of the sub-sites under this site. +// +//nolint:wsl,revive,lll +func (m *ItemSitesSiteItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemSitesSiteItemRequestBuilderGetRequestConfiguration) (msmodel.Siteable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, msmodel.CreateSiteFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(msmodel.Siteable), nil +} diff --git a/src/internal/connector/graph/betasdk/sites/site_item_request_builder.go b/src/internal/connector/graph/betasdk/sites/site_item_request_builder.go new file mode 100644 index 000000000..3746a736c --- /dev/null +++ b/src/internal/connector/graph/betasdk/sites/site_item_request_builder.go @@ -0,0 +1,249 @@ +package sites + +import ( + "context" + + i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go" + msmodel "github.com/microsoftgraph/msgraph-sdk-go/models" + i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0 "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" +) + +// SiteItemRequestBuilder provides operations to manage the collection of site entities. +type SiteItemRequestBuilder struct { + // Path parameters for the request + pathParameters map[string]string + // The request adapter to use to execute the requests. + requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter + // Url template to use to build the URL for the current request builder + urlTemplate string +} + +// SiteItemRequestBuilderGetQueryParameters retrieve properties and relationships for a [site][] resource.A **site** resource represents a team site in SharePoint. +// +//nolint:lll +type SiteItemRequestBuilderGetQueryParameters struct { + // Expand related entities + Expand []string `uriparametername:"%24expand"` + // Select properties to be returned + Select []string `uriparametername:"%24select"` +} + +// SiteItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type SiteItemRequestBuilderGetRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption + // Request query parameters + QueryParameters *SiteItemRequestBuilderGetQueryParameters +} + +// SiteItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options. +// +//nolint:lll +type SiteItemRequestBuilderPatchRequestConfiguration struct { + // Request headers + Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders + // Request options + Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption +} + +// Analytics provides operations to manage the analytics property of the microsoft.graph.site entity. +// REMOVED Analytics for minimial + +// Columns provides operations to manage the columns property of the microsoft.graph.site entity. + +// ColumnsById provides operations to manage the columns property of the microsoft.graph.site entity. + +// NewSiteItemRequestBuilderInternal instantiates a new SiteItemRequestBuilder and sets the default values. +// +//nolint:lll,wsl +func NewSiteItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *SiteItemRequestBuilder { + m := &SiteItemRequestBuilder{} + m.urlTemplate = "{+baseurl}/sites/{site%2Did}{?%24select,%24expand}" + urlTplParams := make(map[string]string) + for idx, item := range pathParameters { + urlTplParams[idx] = item + } + m.pathParameters = urlTplParams + m.requestAdapter = requestAdapter + return m +} + +// NewSiteItemRequestBuilder instantiates a new SiteItemRequestBuilder and sets the default values. +// +//nolint:lll,revive,wsl +func NewSiteItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter) *SiteItemRequestBuilder { + urlParams := make(map[string]string) + urlParams["request-raw-url"] = rawUrl + return NewSiteItemRequestBuilderInternal(urlParams, requestAdapter) +} + +// ContentTypes provides operations to manage the contentTypes property of the microsoft.graph.site entity. + +// ContentTypesById provides operations to manage the contentTypes property of the microsoft.graph.site entity. +// CreateGetRequestInformation retrieve properties and relationships for a [site][] resource.A **site** resource represents a team site in SharePoint. +// +//nolint:lll,wsl +func (m *SiteItemRequestBuilder) CreateGetRequestInformation(ctx context.Context, requestConfiguration *SiteItemRequestBuilderGetRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET + requestInfo.Headers.Add("Accept", "application/json") + if requestConfiguration != nil { + if requestConfiguration.QueryParameters != nil { + requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters)) + } + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + return requestInfo, nil +} + +// CreatePatchRequestInformation update entity in sites by key (id) +// +//nolint:lll,errcheck,wsl +func (m *SiteItemRequestBuilder) CreatePatchRequestInformation(ctx context.Context, body msmodel.Siteable, requestConfiguration *SiteItemRequestBuilderPatchRequestConfiguration) (*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) { + requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation() + requestInfo.UrlTemplate = m.urlTemplate + requestInfo.PathParameters = m.pathParameters + requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH + requestInfo.Headers.Add("Accept", "application/json") + requestInfo.SetContentFromParsable(ctx, m.requestAdapter, "application/json", body) + + if requestConfiguration != nil { + requestInfo.Headers.AddAll(requestConfiguration.Headers) + requestInfo.AddRequestOptions(requestConfiguration.Options) + } + + return requestInfo, nil +} + +// Drive provides operations to manage the drive property of the microsoft.graph.site entity. +// Removed Drive() for minimial connector + +// Drives provides operations to manage the drives property of the microsoft.graph.site entity. +// Removed Drives() + +// DrivesById provides operations to manage the drives property of the microsoft.graph.site entity. + +// ExternalColumns provides operations to manage the externalColumns property of the microsoft.graph.site entity. + +// // ExternalColumnsById provides operations to manage the externalColumns property of the microsoft.graph.site entity. +// +// func (m *SiteItemRequestBuilder) ExternalColumnsById(id string) *ItemExternalColumnsColumnDefinitionItemRequestBuilder { +// urlTplParams := make(map[string]string) +// for idx, item := range m.pathParameters { +// urlTplParams[idx] = item +// } +// if id != "" { +// urlTplParams["columnDefinition%2Did"] = id +// } +// return NewItemExternalColumnsColumnDefinitionItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +// } +// +// Get retrieve properties and relationships for a [site][] resource.A **site** resource represents a team site in SharePoint. +// [Find more info here] +// +// [Find more info here]: https://docs.microsoft.com/graph/api/site-get?view=graph-rest-1.0 +// +//nolint:wsl,revive,lll +func (m *SiteItemRequestBuilder) Get(ctx context.Context, requestConfiguration *SiteItemRequestBuilderGetRequestConfiguration) (msmodel.Siteable, error) { + requestInfo, err := m.CreateGetRequestInformation(ctx, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, msmodel.CreateSiteFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(msmodel.Siteable), nil +} + +//nolint:lll +// GetActivitiesByIntervalWithStartDateTimeWithEndDateTimeWithInterval provides operations to call the getActivitiesByInterval method. +// GetApplicableContentTypesForListWithListId provides operations to call the getApplicableContentTypesForList method. +// GetByPathWithPath provides operations to call the getByPath method. +// InformationProtection provides operations to manage the informationProtection property of the microsoft.graph.site entity. +// Items provides operations to manage the items property of the microsoft.graph.site entity. +// ItemsById provides operations to manage the items property of the microsoft.graph.site entity. +// Lists provides operations to manage the lists property of the microsoft.graph.site entity. +// ListsById provides operations to manage the lists property of the microsoft.graph.site entity. +// Onenote provides operations to manage the onenote property of the microsoft.graph.site entity. +// Operations provides operations to manage the operations property of the microsoft.graph.site entity. +// OperationsById provides operations to manage the operations property of the microsoft.graph.site entity. + +// Pages provides operations to manage the pages property of the microsoft.graph.site entity. +func (m *SiteItemRequestBuilder) Pages() *ItemPagesRequestBuilder { + return NewItemPagesRequestBuilderInternal(m.pathParameters, m.requestAdapter) +} + +// PagesById provides operations to manage the pages property of the microsoft.graph.site entity. +// +//nolint:revive,wsl +func (m *SiteItemRequestBuilder) PagesById(id string) *ItemPagesSitePageItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + if id != "" { + urlTplParams["sitePage%2Did"] = id + } + return NewItemPagesSitePageItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} + +// Patch update entity in sites by key (id) +// +//nolint:wsl,revive,lll +func (m *SiteItemRequestBuilder) Patch( + ctx context.Context, + body msmodel.Siteable, + requestConfiguration *SiteItemRequestBuilderPatchRequestConfiguration, +) (msmodel.Siteable, error) { + requestInfo, err := m.CreatePatchRequestInformation(ctx, body, requestConfiguration) + if err != nil { + return nil, err + } + errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings{ + "4XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + "5XX": i7ad325c11fbf3db4d761c429267362d8b24daa1eda0081f914ebc3cdc85181a0.CreateODataErrorFromDiscriminatorValue, + } + res, err := m.requestAdapter.Send(ctx, requestInfo, msmodel.CreateSiteFromDiscriminatorValue, errorMapping) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(msmodel.Siteable), nil +} + +// Permissions provides operations to manage the permissions property of the microsoft.graph.site entity. +// PermissionsById provides operations to manage the permissions property of the microsoft.graph.site entity. +// Sites provides operations to manage the sites property of the microsoft.graph.site entity. +// func (m *SiteItemRequestBuilder) Sites() +// SitesById provides operations to manage the sites property of the microsoft.graph.site entity. +// +//nolint:revive,wsl +func (m *SiteItemRequestBuilder) SitesById(id string) *ItemSitesSiteItemRequestBuilder { + urlTplParams := make(map[string]string) + for idx, item := range m.pathParameters { + urlTplParams[idx] = item + } + if id != "" { + urlTplParams["site%2Did1"] = id + } + return NewItemSitesSiteItemRequestBuilderInternal(urlTplParams, m.requestAdapter) +} + +// TermStore provides operations to manage the termStore property of the microsoft.graph.site entity. diff --git a/src/internal/connector/graph/errors.go b/src/internal/connector/graph/errors.go index c75e4a6cb..21116057d 100644 --- a/src/internal/connector/graph/errors.go +++ b/src/internal/connector/graph/errors.go @@ -17,6 +17,7 @@ import ( // --------------------------------------------------------------------------- const ( + errCodeActivityLimitReached = "activityLimitReached" errCodeItemNotFound = "ErrorItemNotFound" errCodeEmailFolderNotFound = "ErrorSyncFolderNotFound" errCodeResyncRequired = "ResyncRequired" @@ -31,8 +32,10 @@ var ( // normally the graph client will catch this for us, but in case we // run our own client Do(), we need to translate it to a timeout type // failure locally. - Err429TooManyRequests = errors.New("429 too many requests") - Err503ServiceUnavailable = errors.New("503 Service Unavailable") + Err429TooManyRequests = errors.New("429 too many requests") + Err503ServiceUnavailable = errors.New("503 Service Unavailable") + Err504GatewayTimeout = errors.New("504 Gateway Timeout") + Err500InternalServerError = errors.New("500 Internal Server Error") ) // The folder or item was deleted between the time we identified @@ -113,6 +116,10 @@ func IsErrThrottled(err error) bool { return true } + if hasErrorCode(err, errCodeActivityLimitReached) { + return true + } + e := ErrThrottled{} return errors.As(err, &e) @@ -135,21 +142,18 @@ func IsErrUnauthorized(err error) bool { return errors.As(err, &e) } -type ErrServiceUnavailable struct { +type ErrInternalServerError struct { common.Err } -func IsSericeUnavailable(err error) bool { - if errors.Is(err, Err503ServiceUnavailable) { +func IsInternalServerError(err error) bool { + if errors.Is(err, Err500InternalServerError) { return true } - e := ErrUnauthorized{} - if errors.As(err, &e) { - return true - } + e := ErrInternalServerError{} - return true + return errors.As(err, &e) } // --------------------------------------------------------------------------- diff --git a/src/internal/connector/graph/errors_test.go b/src/internal/connector/graph/errors_test.go new file mode 100644 index 000000000..c7f889b83 --- /dev/null +++ b/src/internal/connector/graph/errors_test.go @@ -0,0 +1,248 @@ +package graph + +import ( + "context" + "testing" + + "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + + "github.com/alcionai/corso/src/internal/common" +) + +type GraphErrorsUnitSuite struct { + suite.Suite +} + +func TestGraphErrorsUnitSuite(t *testing.T) { + suite.Run(t, new(GraphErrorsUnitSuite)) +} + +func odErr(code string) *odataerrors.ODataError { + odErr := &odataerrors.ODataError{} + merr := odataerrors.MainError{} + merr.SetCode(&code) + odErr.SetError(&merr) + + return odErr +} + +func (suite *GraphErrorsUnitSuite) TestIsErrDeletedInFlight() { + table := []struct { + name string + err error + expect assert.BoolAssertionFunc + }{ + { + name: "nil", + err: nil, + expect: assert.False, + }, + { + name: "non-matching", + err: assert.AnError, + expect: assert.False, + }, + { + name: "as", + err: ErrDeletedInFlight{Err: *common.EncapsulateError(assert.AnError)}, + expect: assert.True, + }, + { + name: "non-matching oDataErr", + err: odErr("fnords"), + expect: assert.False, + }, + { + name: "not-found oDataErr", + err: odErr(errCodeItemNotFound), + expect: assert.True, + }, + { + name: "sync-not-found oDataErr", + err: odErr(errCodeSyncFolderNotFound), + expect: assert.True, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + test.expect(t, IsErrDeletedInFlight(test.err)) + }) + } +} + +func (suite *GraphErrorsUnitSuite) TestIsErrInvalidDelta() { + table := []struct { + name string + err error + expect assert.BoolAssertionFunc + }{ + { + name: "nil", + err: nil, + expect: assert.False, + }, + { + name: "non-matching", + err: assert.AnError, + expect: assert.False, + }, + { + name: "as", + err: ErrInvalidDelta{Err: *common.EncapsulateError(assert.AnError)}, + expect: assert.True, + }, + { + name: "non-matching oDataErr", + err: odErr("fnords"), + expect: assert.False, + }, + { + name: "resync-required oDataErr", + err: odErr(errCodeResyncRequired), + expect: assert.True, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + test.expect(t, IsErrInvalidDelta(test.err)) + }) + } +} + +func (suite *GraphErrorsUnitSuite) TestIsErrTimeout() { + table := []struct { + name string + err error + expect assert.BoolAssertionFunc + }{ + { + name: "nil", + err: nil, + expect: assert.False, + }, + { + name: "non-matching", + err: assert.AnError, + expect: assert.False, + }, + { + name: "as", + err: ErrTimeout{Err: *common.EncapsulateError(assert.AnError)}, + expect: assert.True, + }, + { + name: "context deadline", + err: context.DeadlineExceeded, + expect: assert.True, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + test.expect(t, IsErrTimeout(test.err)) + }) + } +} + +func (suite *GraphErrorsUnitSuite) TestIsErrThrottled() { + table := []struct { + name string + err error + expect assert.BoolAssertionFunc + }{ + { + name: "nil", + err: nil, + expect: assert.False, + }, + { + name: "non-matching", + err: assert.AnError, + expect: assert.False, + }, + { + name: "as", + err: ErrThrottled{Err: *common.EncapsulateError(assert.AnError)}, + expect: assert.True, + }, + { + name: "is429", + err: Err429TooManyRequests, + expect: assert.True, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + test.expect(t, IsErrThrottled(test.err)) + }) + } +} + +func (suite *GraphErrorsUnitSuite) TestIsErrUnauthorized() { + table := []struct { + name string + err error + expect assert.BoolAssertionFunc + }{ + { + name: "nil", + err: nil, + expect: assert.False, + }, + { + name: "non-matching", + err: assert.AnError, + expect: assert.False, + }, + { + name: "as", + err: ErrUnauthorized{Err: *common.EncapsulateError(assert.AnError)}, + expect: assert.True, + }, + { + name: "is429", + err: Err401Unauthorized, + expect: assert.True, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + test.expect(t, IsErrUnauthorized(test.err)) + }) + } +} + +func (suite *GraphErrorsUnitSuite) TestIsInternalServerError() { + table := []struct { + name string + err error + expect assert.BoolAssertionFunc + }{ + { + name: "nil", + err: nil, + expect: assert.False, + }, + { + name: "non-matching", + err: assert.AnError, + expect: assert.False, + }, + { + name: "as", + err: ErrInternalServerError{Err: *common.EncapsulateError(assert.AnError)}, + expect: assert.True, + }, + { + name: "is429", + err: Err500InternalServerError, + expect: assert.True, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + test.expect(t, IsInternalServerError(test.err)) + }) + } +} diff --git a/src/internal/connector/graph/service.go b/src/internal/connector/graph/service.go index 6c0e6dbc1..093995a42 100644 --- a/src/internal/connector/graph/service.go +++ b/src/internal/connector/graph/service.go @@ -149,7 +149,7 @@ func HTTPClient(opts ...option) *http.Client { middlewares := msgraphgocore.GetDefaultMiddlewaresWithOptions(&clientOptions) middlewares = append(middlewares, &LoggingMiddleware{}) httpClient := msgraphgocore.GetDefaultClient(&clientOptions, middlewares...) - httpClient.Timeout = time.Second * 90 + httpClient.Timeout = time.Minute * 3 (&clientConfig{}). populate(opts...). @@ -250,7 +250,6 @@ func (handler *LoggingMiddleware) Intercept( respDump, _ := httputil.DumpResponse(resp, false) metadata := []any{ - "idx", middlewareIndex, "method", req.Method, "status", resp.Status, "statusCode", resp.StatusCode, @@ -273,7 +272,6 @@ func (handler *LoggingMiddleware) Intercept( respDump, _ := httputil.DumpResponse(resp, true) metadata := []any{ - "idx", middlewareIndex, "method", req.Method, "status", resp.Status, "statusCode", resp.StatusCode, diff --git a/src/internal/connector/graph/service_test.go b/src/internal/connector/graph/service_test.go index 14bdc9c36..c2ef2d699 100644 --- a/src/internal/connector/graph/service_test.go +++ b/src/internal/connector/graph/service_test.go @@ -53,7 +53,7 @@ func (suite *GraphUnitSuite) TestHTTPClient() { name: "no options", opts: []option{}, check: func(t *testing.T, c *http.Client) { - assert.Equal(t, 90*time.Second, c.Timeout, "default timeout") + assert.Equal(t, 3*time.Minute, c.Timeout, "default timeout") }, }, { diff --git a/src/internal/connector/graph_connector.go b/src/internal/connector/graph_connector.go index 3dbc0e60c..def430f14 100644 --- a/src/internal/connector/graph_connector.go +++ b/src/internal/connector/graph_connector.go @@ -266,9 +266,11 @@ func (gc *GraphConnector) UnionSiteIDsAndWebURLs(ctx context.Context, ids, urls // SideEffect: gc.status is updated at the completion of operation func (gc *GraphConnector) RestoreDataCollections( ctx context.Context, + backupVersion int, acct account.Account, selector selectors.Selector, dest control.RestoreDestination, + opts control.Options, dcs []data.Collection, ) (*details.Details, error) { ctx, end := D.Span(ctx, "connector:restore") @@ -289,9 +291,9 @@ func (gc *GraphConnector) RestoreDataCollections( case selectors.ServiceExchange: status, err = exchange.RestoreExchangeDataCollections(ctx, creds, gc.Service, dest, dcs, deets) case selectors.ServiceOneDrive: - status, err = onedrive.RestoreCollections(ctx, gc.Service, dest, dcs, deets) + status, err = onedrive.RestoreCollections(ctx, backupVersion, gc.Service, dest, opts, dcs, deets) case selectors.ServiceSharePoint: - status, err = sharepoint.RestoreCollections(ctx, gc.Service, dest, dcs, deets) + status, err = sharepoint.RestoreCollections(ctx, backupVersion, gc.Service, dest, dcs, deets) default: err = errors.Errorf("restore data from service %s not supported", selector.Service.String()) } diff --git a/src/internal/connector/graph_connector_helper_test.go b/src/internal/connector/graph_connector_helper_test.go index ce16a5a4d..539cbf501 100644 --- a/src/internal/connector/graph_connector_helper_test.go +++ b/src/internal/connector/graph_connector_helper_test.go @@ -2,9 +2,11 @@ package connector import ( "context" + "encoding/json" "io" "net/http" "reflect" + "strings" "testing" "github.com/microsoftgraph/msgraph-sdk-go/models" @@ -14,6 +16,7 @@ import ( "golang.org/x/exp/maps" "github.com/alcionai/corso/src/internal/connector/mockconnector" + "github.com/alcionai/corso/src/internal/connector/onedrive" "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/tester" @@ -169,6 +172,14 @@ type restoreBackupInfo struct { resource resource } +type restoreBackupInfoMultiVersion struct { + name string + service path.ServiceType + collectionsLatest []colInfo + collectionsPrevious []colInfo + resource resource +} + func attachmentEqual( expected models.Attachmentable, got models.Attachmentable, @@ -336,12 +347,12 @@ func checkContact( testEmptyOrEqual(t, expected.GetAssistantName(), got.GetAssistantName(), "AssistantName") testEmptyOrEqual(t, expected.GetBirthday(), got.GetBirthday(), "Birthday") - - assert.Equal(t, expected.GetBusinessAddress(), got.GetBusinessAddress()) - - testEmptyOrEqual(t, expected.GetBusinessHomePage(), got.GetBusinessHomePage(), "BusinessHomePage") - - assert.Equal(t, expected.GetBusinessPhones(), got.GetBusinessPhones()) + // Not present in msgraph-beta-sdk/models + // assert.Equal(t, expected.GetBusinessAddress(), got.GetBusinessAddress()) + // Not present in msgraph-beta-sdk/models + // testEmptyOrEqual(t, expected.GetBusinessHomePage(), got.GetBusinessHomePage(), "BusinessHomePage") + // Not present in msgraph-beta-sdk/models + // assert.Equal(t, expected.GetBusinessPhones(), got.GetBusinessPhones()) assert.Equal(t, expected.GetCategories(), got.GetCategories()) @@ -365,9 +376,10 @@ func checkContact( testEmptyOrEqual(t, expected.GetGivenName(), got.GetGivenName(), "GivenName") - assert.Equal(t, expected.GetHomeAddress(), got.GetHomeAddress()) - - assert.Equal(t, expected.GetHomePhones(), got.GetHomePhones()) + // Not present in msgraph-beta-sdk/models + // assert.Equal(t, expected.GetHomeAddress(), got.GetHomeAddress()) + // Not present in msgraph-beta-sdk/models + // assert.Equal(t, expected.GetHomePhones(), got.GetHomePhones()) // Skip CreatedDateTime as it's tied to this specific instance of the item. @@ -383,13 +395,14 @@ func checkContact( testEmptyOrEqual(t, expected.GetMiddleName(), got.GetMiddleName(), "MiddleName") - testEmptyOrEqual(t, expected.GetMobilePhone(), got.GetMobilePhone(), "MobilePhone") + // Not present in msgraph-beta-sdk/models + // testEmptyOrEqual(t, expected.GetMobilePhone(), got.GetMobilePhone(), "MobilePhone") testEmptyOrEqual(t, expected.GetNickName(), got.GetNickName(), "NickName") testEmptyOrEqual(t, expected.GetOfficeLocation(), got.GetOfficeLocation(), "OfficeLocation") - - assert.Equal(t, expected.GetOtherAddress(), got.GetOtherAddress()) + // Not present in msgraph-beta-sdk/models + // assert.Equal(t, expected.GetOtherAddress(), got.GetOtherAddress()) // Skip ParentFolderId as it's tied to this specific instance of the item. @@ -643,21 +656,52 @@ func compareOneDriveItem( t *testing.T, expected map[string][]byte, item data.Stream, + restorePermissions bool, ) { + name := item.UUID() + expectedData := expected[item.UUID()] - if !assert.NotNil(t, expectedData, "unexpected file with name %s", item.UUID) { + if !assert.NotNil(t, expectedData, "unexpected file with name %s", item.UUID()) { return } - // OneDrive items are just byte buffers of the data. Nothing special to - // interpret. May need to do chunked comparisons in the future if we test - // large item equality. buf, err := io.ReadAll(item.ToReader()) if !assert.NoError(t, err) { return } - assert.Equal(t, expectedData, buf) + if !strings.HasSuffix(name, onedrive.MetaFileSuffix) && !strings.HasSuffix(name, onedrive.DirMetaFileSuffix) { + // OneDrive data items are just byte buffers of the data. Nothing special to + // interpret. May need to do chunked comparisons in the future if we test + // large item equality. + assert.Equal(t, expectedData, buf) + return + } + + var ( + itemMeta onedrive.Metadata + expectedMeta onedrive.Metadata + ) + + err = json.Unmarshal(buf, &itemMeta) + assert.Nil(t, err) + + err = json.Unmarshal(expectedData, &expectedMeta) + assert.Nil(t, err) + + if !restorePermissions { + assert.Equal(t, 0, len(itemMeta.Permissions)) + return + } + + assert.Equal(t, len(expectedMeta.Permissions), len(itemMeta.Permissions), "number of permissions after restore") + + // FIXME(meain): The permissions before and after might not be in the same order. + for i, p := range expectedMeta.Permissions { + assert.Equal(t, p.Email, itemMeta.Permissions[i].Email) + assert.Equal(t, p.Roles, itemMeta.Permissions[i].Roles) + assert.Equal(t, p.Expiration, itemMeta.Permissions[i].Expiration) + } } func compareItem( @@ -666,6 +710,7 @@ func compareItem( service path.ServiceType, category path.CategoryType, item data.Stream, + restorePermissions bool, ) { if mt, ok := item.(data.StreamModTime); ok { assert.NotZero(t, mt.ModTime()) @@ -685,7 +730,7 @@ func compareItem( } case path.OneDriveService: - compareOneDriveItem(t, expected, item) + compareOneDriveItem(t, expected, item, restorePermissions) default: assert.FailNowf(t, "unexpected service: %s", service.String()) @@ -718,6 +763,7 @@ func checkCollections( expectedItems int, expected map[string]map[string][]byte, got []data.Collection, + restorePermissions bool, ) int { collectionsWithItems := []data.Collection{} @@ -752,7 +798,7 @@ func checkCollections( continue } - compareItem(t, expectedColData, service, category, item) + compareItem(t, expectedColData, service, category, item, restorePermissions) } if gotItems != startingItems { @@ -904,10 +950,63 @@ func collectionsForInfo( tenant, user string, dest control.RestoreDestination, allInfo []colInfo, -) (int, []data.Collection, map[string]map[string][]byte) { +) (int, int, []data.Collection, map[string]map[string][]byte) { collections := make([]data.Collection, 0, len(allInfo)) expectedData := make(map[string]map[string][]byte, len(allInfo)) totalItems := 0 + kopiaEntries := 0 + + for _, info := range allInfo { + pth := mustToDataLayerPath( + t, + service, + tenant, + user, + info.category, + info.pathElements, + false, + ) + c := mockconnector.NewMockExchangeCollection(pth, len(info.items)) + baseDestPath := backupOutputPathFromRestore(t, dest, pth) + + baseExpected := expectedData[baseDestPath.String()] + if baseExpected == nil { + expectedData[baseDestPath.String()] = make(map[string][]byte, len(info.items)) + baseExpected = expectedData[baseDestPath.String()] + } + + for i := 0; i < len(info.items); i++ { + c.Names[i] = info.items[i].name + c.Data[i] = info.items[i].data + + baseExpected[info.items[i].lookupKey] = info.items[i].data + + // We do not count metadata files against item count + if service != path.OneDriveService || + (service == path.OneDriveService && + strings.HasSuffix(info.items[i].name, onedrive.DataFileSuffix)) { + totalItems++ + } + } + + collections = append(collections, c) + kopiaEntries += len(info.items) + } + + return totalItems, kopiaEntries, collections, expectedData +} + +func collectionsForInfoVersion0( + t *testing.T, + service path.ServiceType, + tenant, user string, + dest control.RestoreDestination, + allInfo []colInfo, +) (int, int, []data.Collection, map[string]map[string][]byte) { + collections := make([]data.Collection, 0, len(allInfo)) + expectedData := make(map[string]map[string][]byte, len(allInfo)) + totalItems := 0 + kopiaEntries := 0 for _, info := range allInfo { pth := mustToDataLayerPath( @@ -937,9 +1036,10 @@ func collectionsForInfo( collections = append(collections, c) totalItems += len(info.items) + kopiaEntries += len(info.items) } - return totalItems, collections, expectedData + return totalItems, kopiaEntries, collections, expectedData } //nolint:deadcode diff --git a/src/internal/connector/graph_connector_test.go b/src/internal/connector/graph_connector_test.go index 1ed353be6..b3b55a15e 100644 --- a/src/internal/connector/graph_connector_test.go +++ b/src/internal/connector/graph_connector_test.go @@ -2,6 +2,8 @@ package connector import ( "context" + "encoding/base64" + "encoding/json" "strings" "testing" "time" @@ -15,10 +17,12 @@ import ( "github.com/alcionai/corso/src/internal/connector/discovery/api" "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/mockconnector" + "github.com/alcionai/corso/src/internal/connector/onedrive" "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/pkg/account" + "github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/selectors" @@ -135,9 +139,10 @@ func (suite *GraphConnectorUnitSuite) TestUnionSiteIDsAndWebURLs() { type GraphConnectorIntegrationSuite struct { suite.Suite - connector *GraphConnector - user string - acct account.Account + connector *GraphConnector + user string + secondaryUser string + acct account.Account } func TestGraphConnectorIntegrationSuite(t *testing.T) { @@ -158,6 +163,7 @@ func (suite *GraphConnectorIntegrationSuite) SetupSuite() { suite.connector = loadConnector(ctx, suite.T(), graph.HTTPClient(graph.NoTimeout()), Users) suite.user = tester.M365UserID(suite.T()) + suite.secondaryUser = tester.SecondaryM365UserID(suite.T()) suite.acct = tester.NewM365Account(suite.T()) tester.LogTimeOfTest(suite.T()) @@ -226,7 +232,18 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreFailsBadService() { } ) - deets, err := suite.connector.RestoreDataCollections(ctx, acct, sel, dest, nil) + deets, err := suite.connector.RestoreDataCollections( + ctx, + backup.Version, + acct, + sel, + dest, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + nil, + ) assert.Error(t, err) assert.NotNil(t, deets) @@ -294,10 +311,16 @@ func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() { deets, err := suite.connector.RestoreDataCollections( ctx, + backup.Version, suite.acct, test.sel, dest, - test.col) + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + test.col, + ) require.NoError(t, err) assert.NotNil(t, deets) @@ -344,11 +367,13 @@ func runRestoreBackupTest( test restoreBackupInfo, tenant string, resourceOwners []string, + opts control.Options, ) { var ( - collections []data.Collection - expectedData = map[string]map[string][]byte{} - totalItems = 0 + collections []data.Collection + expectedData = map[string]map[string][]byte{} + totalItems = 0 + totalKopiaItems = 0 // Get a dest per test so they're independent. dest = tester.DefaultTestRestoreDestination() ) @@ -357,7 +382,7 @@ func runRestoreBackupTest( defer flush() for _, owner := range resourceOwners { - numItems, ownerCollections, userExpectedData := collectionsForInfo( + numItems, kopiaItems, ownerCollections, userExpectedData := collectionsForInfo( t, test.service, tenant, @@ -368,6 +393,7 @@ func runRestoreBackupTest( collections = append(collections, ownerCollections...) totalItems += numItems + totalKopiaItems += kopiaItems maps.Copy(expectedData, userExpectedData) } @@ -383,10 +409,13 @@ func runRestoreBackupTest( restoreSel := getSelectorWith(t, test.service, resourceOwners, true) deets, err := restoreGC.RestoreDataCollections( ctx, + backup.Version, acct, restoreSel, dest, - collections) + opts, + collections, + ) require.NoError(t, err) assert.NotNil(t, deets) @@ -425,14 +454,24 @@ func runRestoreBackupTest( t.Logf("Selective backup of %s\n", backupSel) start = time.Now() - dcs, err := backupGC.DataCollections(ctx, backupSel, nil, control.Options{}) + dcs, excludes, err := backupGC.DataCollections( + ctx, + backupSel, + nil, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) require.NoError(t, err) + // No excludes yet because this isn't an incremental backup. + assert.Empty(t, excludes) t.Logf("Backup enumeration complete in %v\n", time.Since(start)) // Pull the data prior to waiting for the status as otherwise it will // deadlock. - skipped := checkCollections(t, totalItems, expectedData, dcs) + skipped := checkCollections(t, totalKopiaItems, expectedData, dcs, opts.RestorePermissions) status = backupGC.AwaitStatus() @@ -444,6 +483,143 @@ func runRestoreBackupTest( "backup status.Successful; wanted %d items + %d skipped", totalItems, skipped) } +// runRestoreBackupTestVersion0 restores with data from an older +// version of the backup and check the restored data against the +// something that would be in the form of a newer backup. +func runRestoreBackupTestVersion0( + t *testing.T, + acct account.Account, + test restoreBackupInfoMultiVersion, + tenant string, + resourceOwners []string, + opts control.Options, +) { + var ( + collections []data.Collection + expectedData = map[string]map[string][]byte{} + totalItems = 0 + totalKopiaItems = 0 + // Get a dest per test so they're independent. + dest = tester.DefaultTestRestoreDestination() + ) + + ctx, flush := tester.NewContext() + defer flush() + + for _, owner := range resourceOwners { + _, _, ownerCollections, _ := collectionsForInfoVersion0( + t, + test.service, + tenant, + owner, + dest, + test.collectionsPrevious, + ) + + collections = append(collections, ownerCollections...) + } + + t.Logf( + "Restoring collections to %s for resourceOwners(s) %v\n", + dest.ContainerName, + resourceOwners, + ) + + start := time.Now() + + restoreGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) + restoreSel := getSelectorWith(t, test.service, resourceOwners, true) + deets, err := restoreGC.RestoreDataCollections( + ctx, + 0, // The OG version ;) + acct, + restoreSel, + dest, + opts, + collections, + ) + require.NoError(t, err) + assert.NotNil(t, deets) + + assert.NotNil(t, restoreGC.AwaitStatus()) + + runTime := time.Since(start) + + t.Logf("Restore complete in %v\n", runTime) + + // Run a backup and compare its output with what we put in. + for _, owner := range resourceOwners { + numItems, kopiaItems, _, userExpectedData := collectionsForInfo( + t, + test.service, + tenant, + owner, + dest, + test.collectionsLatest, + ) + + totalItems += numItems + totalKopiaItems += kopiaItems + + maps.Copy(expectedData, userExpectedData) + } + + cats := make(map[path.CategoryType]struct{}, len(test.collectionsLatest)) + for _, c := range test.collectionsLatest { + cats[c.category] = struct{}{} + } + + expectedDests := make([]destAndCats, 0, len(resourceOwners)) + for _, ro := range resourceOwners { + expectedDests = append(expectedDests, destAndCats{ + resourceOwner: ro, + dest: dest.ContainerName, + cats: cats, + }) + } + + backupGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) + backupSel := backupSelectorForExpected(t, test.service, expectedDests) + + start = time.Now() + dcs, excludes, err := backupGC.DataCollections( + ctx, + backupSel, + nil, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + require.NoError(t, err) + // No excludes yet because this isn't an incremental backup. + assert.Empty(t, excludes) + + t.Logf("Backup enumeration complete in %v\n", time.Since(start)) + + // Pull the data prior to waiting for the status as otherwise it will + // deadlock. + skipped := checkCollections(t, totalKopiaItems, expectedData, dcs, opts.RestorePermissions) + + status := backupGC.AwaitStatus() + assert.Equal(t, totalItems+skipped, status.ObjectCount, "status.ObjectCount") + assert.Equal(t, totalItems+skipped, status.Successful, "status.Successful") +} + +func getTestMetaJSON(t *testing.T, user string, roles []string) []byte { + id := base64.StdEncoding.EncodeToString([]byte(user + strings.Join(roles, "+"))) + testMeta := onedrive.Metadata{Permissions: []onedrive.UserPermission{ + {ID: id, Roles: roles, Email: user}, + }} + + testMetaJSON, err := json.Marshal(testMeta) + if err != nil { + t.Fatal("unable to marshall test permissions", err) + } + + return testMetaJSON +} + func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { bodyText := "This email has some text. However, all the text is on the same line." subjectText := "Test message for restore" @@ -562,7 +738,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { }, }, { - name: "MultipleContactsMutlipleFolders", + name: "MultipleContactsMultipleFolders", service: path.ExchangeService, resource: Users, collections: []colInfo{ @@ -680,6 +856,226 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { service: path.OneDriveService, resource: Users, collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "folder-a" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("b", 65)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("c", 129)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "folder-a" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + "folder-a", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("d", 257)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 257)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + { + name: "OneDriveFoldersAndFilesWithMetadata", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 66)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTest( + t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} + +func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackupVersion0() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + table := []restoreBackupInfoMultiVersion{ + { + name: "OneDriveMultipleFoldersAndFiles", + service: path.OneDriveService, + resource: Users, + + collectionsPrevious: []colInfo{ { pathElements: []string{ "drives", @@ -763,12 +1159,152 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() { }, }, }, + + collectionsLatest: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "folder-a" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("b", 65)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("c", 129)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "folder-a" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "folder-a" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "folder-a", + "b", + "folder-a", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("d", 257)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 257)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, }, } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { - runRestoreBackupTest(t, suite.acct, test, suite.connector.tenant, []string{suite.user}) + runRestoreBackupTestVersion0( + t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) }) } } @@ -855,7 +1391,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames }, }) - totalItems, collections, expectedData := collectionsForInfo( + totalItems, _, collections, expectedData := collectionsForInfo( t, test.service, suite.connector.tenant, @@ -877,7 +1413,18 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames ) restoreGC := loadConnector(ctx, t, graph.HTTPClient(graph.NoTimeout()), test.resource) - deets, err := restoreGC.RestoreDataCollections(ctx, suite.acct, restoreSel, dest, collections) + deets, err := restoreGC.RestoreDataCollections( + ctx, + backup.Version, + suite.acct, + restoreSel, + dest, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + collections, + ) require.NoError(t, err) require.NotNil(t, deets) @@ -898,14 +1445,24 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames backupSel := backupSelectorForExpected(t, test.service, expectedDests) t.Log("Selective backup of", backupSel) - dcs, err := backupGC.DataCollections(ctx, backupSel, nil, control.Options{}) + dcs, excludes, err := backupGC.DataCollections( + ctx, + backupSel, + nil, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) require.NoError(t, err) + // No excludes yet because this isn't an incremental backup. + assert.Empty(t, excludes) t.Log("Backup enumeration complete") // Pull the data prior to waiting for the status as otherwise it will // deadlock. - skipped := checkCollections(t, allItems, allExpectedData, dcs) + skipped := checkCollections(t, allItems, allExpectedData, dcs, true) status := backupGC.AwaitStatus() assert.Equal(t, allItems+skipped, status.ObjectCount, "status.ObjectCount") @@ -914,6 +1471,319 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames } } +func (suite *GraphConnectorIntegrationSuite) TestPermissionsRestoreAndBackup() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + table := []restoreBackupInfo{ + { + name: "FilePermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + + { + name: "FileInsideFolderPermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: []byte("{}"), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 66)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + + { + name: "FileAndFolderPermissionsResote", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + { + name: "b" + onedrive.DirMetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 66)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + + { + name: "FileAndFolderSeparatePermissionsResote", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "b" + onedrive.DirMetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 66)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + + { + name: "FolderAndNoChildPermissionsResote", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "b" + onedrive.DirMetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"read"}), + lookupKey: "b" + onedrive.DirMetaFileSuffix, + }, + }, + }, + { + pathElements: []string{ + "drives", + driveID, + "root:", + "b", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("e", 66)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: []byte("{}"), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTest(t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} + +func (suite *GraphConnectorIntegrationSuite) TestPermissionsBackupAndNoRestore() { + ctx, flush := tester.NewContext() + defer flush() + + // Get the default drive ID for the test user. + driveID := mustGetDefaultDriveID( + suite.T(), + ctx, + suite.connector.Service, + suite.user, + ) + + table := []restoreBackupInfo{ + { + name: "FilePermissionsRestore", + service: path.OneDriveService, + resource: Users, + collections: []colInfo{ + { + pathElements: []string{ + "drives", + driveID, + "root:", + }, + category: path.FilesCategory, + items: []itemInfo{ + { + name: "test-file.txt" + onedrive.DataFileSuffix, + data: []byte(strings.Repeat("a", 33)), + lookupKey: "test-file.txt" + onedrive.DataFileSuffix, + }, + { + name: "test-file.txt" + onedrive.MetaFileSuffix, + data: getTestMetaJSON(suite.T(), suite.secondaryUser, []string{"write"}), + lookupKey: "test-file.txt" + onedrive.MetaFileSuffix, + }, + }, + }, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + runRestoreBackupTest( + t, + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) + }) + } +} + // TODO: this should only be run during smoke tests, not part of the standard CI. // That's why it's set aside instead of being included in the other test set. func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup_largeMailAttachment() { @@ -938,5 +1808,15 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup_largeMailAttac }, } - runRestoreBackupTest(suite.T(), suite.acct, test, suite.connector.tenant, []string{suite.user}) + runRestoreBackupTest( + suite.T(), + suite.acct, + test, + suite.connector.tenant, + []string{suite.user}, + control.Options{ + RestorePermissions: true, + ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}, + }, + ) } diff --git a/src/internal/connector/mockconnector/mock_data_message.go b/src/internal/connector/mockconnector/mock_data_message.go index 597447492..da06cbaab 100644 --- a/src/internal/connector/mockconnector/mock_data_message.go +++ b/src/internal/connector/mockconnector/mock_data_message.go @@ -336,3 +336,26 @@ func GetMockEventMessageRequest(subject string) []byte { return []byte(message) } + +func GetMockMessageWithItemAttachmentEvent(subject string) []byte { + //nolint:lll + message := "{\"id\":\"AAMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOABGAAAAAAAPvVwUramXT7jlSGpVU8_7BwB8wYc0thTTTYl3RpEYIUq_AAAAAAEMAAB8wYc0thTTTYl3RpEYIUq_AADFfThMAAA=\",\"@odata.type\":\"#microsoft.graph.message\"," + + "\"@odata.etag\":\"W/\\\"CQAAABYAAAB8wYc0thTTTYl3RpEYIUq+AADFK3BH\\\"\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('dustina%408qzvrj.onmicrosoft.com')/messages/$entity\",\"categories\":[]," + + "\"changeKey\":\"CQAAABYAAAB8wYc0thTTTYl3RpEYIUq+AADFK3BH\",\"createdDateTime\":\"2023-02-01T13:48:43Z\",\"lastModifiedDateTime\":\"2023-02-01T18:27:03Z\"," + + "\"attachments\":[{\"id\":\"AAMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOABGAAAAAAAPvVwUramXT7jlSGpVU8_7BwB8wYc0thTTTYl3RpEYIUq_AAAAAAEMAAB8wYc0thTTTYl3RpEYIUq_AADFfThMAAABEgAQAKHxTL6mNCZPo71dbwrfKYM=\"," + + "\"@odata.type\":\"#microsoft.graph.itemAttachment\",\"isInline\":false,\"lastModifiedDateTime\":\"2023-02-01T13:52:56Z\",\"name\":\"Holidayevent\",\"size\":2059,\"item\":{\"id\":\"\",\"@odata.type\":\"#microsoft.graph.event\"," + + "\"createdDateTime\":\"2023-02-01T13:52:56Z\",\"lastModifiedDateTime\":\"2023-02-01T13:52:56Z\",\"body\":{\"content\":\"\\r\\nLet'slookforfunding!\"," + + "\"contentType\":\"html\"},\"end\":{\"dateTime\":\"2016-12-02T19:00:00.0000000Z\",\"timeZone\":\"UTC\"}," + + "\"hasAttachments\":false,\"isAllDay\":false,\"isCancelled\":false,\"isDraft\":true,\"isOnlineMeeting\":false,\"isOrganizer\":true,\"isReminderOn\":false,\"organizer\":{\"emailAddress\":{\"address\":\"" + defaultMessageFrom + "\",\"name\":\"" + defaultAlias + "\"}}," + + "\"originalEndTimeZone\":\"tzone://Microsoft/Utc\",\"originalStartTimeZone\":\"tzone://Microsoft/Utc\",\"reminderMinutesBeforeStart\":0,\"responseRequested\":true,\"start\":{\"dateTime\":\"2016-12-02T18:00:00.0000000Z\",\"timeZone\":\"UTC\"}," + + "\"subject\":\"Discussgiftsforchildren\",\"type\":\"singleInstance\"}}],\"bccRecipients\":[],\"body\":{\"content\":\"\\r\\n\\r\\n\\r\\nLookingtodothis \",\"contentType\":\"html\"}," + + "\"bodyPreview\":\"Lookingtodothis\",\"ccRecipients\":[],\"conversationId\":\"AAQkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOAAQADGvj5ACBMdGpESX4xSOxCo=\",\"conversationIndex\":\"AQHZNkPmMa+PkAIEx0akRJfjFI7EKg==\",\"flag\":{\"flagStatus\":\"notFlagged\"}," + + "\"from\":{\"emailAddress\":{\"address\":\"" + defaultMessageFrom + "\",\"name\":\"" + defaultAlias + "\"}},\"hasAttachments\":true,\"importance\":\"normal\",\"inferenceClassification\":\"focused\"," + + "\"internetMessageId\":\"\",\"isDeliveryReceiptRequested\":false,\"isDraft\":false,\"isRead\":true,\"isReadReceiptRequested\":false," + + "\"parentFolderId\":\"AQMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4ADVkZWQwNmNlMTgALgAAAw_9XBStqZdPuOVIalVTz7sBAHzBhzS2FNNNiXdGkRghSr4AAAIBDAAAAA==\",\"receivedDateTime\":\"2023-02-01T13:48:47Z\",\"replyTo\":[]," + + "\"sender\":{\"emailAddress\":{\"address\":\"" + defaultMessageSender + "\",\"name\":\"" + defaultAlias + "\"}},\"sentDateTime\":\"2023-02-01T13:48:46Z\"," + + "\"subject\":\"" + subject + "\",\"toRecipients\":[{\"emailAddress\":{\"address\":\"" + defaultMessageTo + "\",\"name\":\"" + defaultAlias + "\"}}]," + + "\"webLink\":\"https://outlook.office365.com/owa/?ItemID=AAMkAGQ1NzViZTdhLTEwMTMtNGJjNi05YWI2LTg4NWRlZDA2Y2UxOABGAAAAAAAPvVwUramXT7jlSGpVU8%2B7BwB8wYc0thTTTYl3RpEYIUq%2BAAAAAAEMAAB8wYc0thTTTYl3RpEYIUq%2BAADFfThMAAA%3D&exvsurl=1&viewmodel=ReadMessageItem\"}" + + return []byte(message) +} diff --git a/src/internal/connector/onedrive/api/drive.go b/src/internal/connector/onedrive/api/drive.go index 6dd7d46a1..fea6e53a7 100644 --- a/src/internal/connector/onedrive/api/drive.go +++ b/src/internal/connector/onedrive/api/drive.go @@ -3,6 +3,7 @@ package api import ( "context" + msdrives "github.com/microsoftgraph/msgraph-sdk-go/drives" "github.com/microsoftgraph/msgraph-sdk-go/models" mssites "github.com/microsoftgraph/msgraph-sdk-go/sites" msusers "github.com/microsoftgraph/msgraph-sdk-go/users" @@ -12,6 +13,65 @@ import ( "github.com/alcionai/corso/src/internal/connector/graph/api" ) +func getValues[T any](l api.PageLinker) ([]T, error) { + page, ok := l.(interface{ GetValue() []T }) + if !ok { + return nil, errors.Errorf( + "response of type [%T] does not comply with GetValue() interface", + l, + ) + } + + return page.GetValue(), nil +} + +// max we can do is 999 +const pageSize = int32(999) + +type driveItemPager struct { + gs graph.Servicer + builder *msdrives.ItemRootDeltaRequestBuilder + options *msdrives.ItemRootDeltaRequestBuilderGetRequestConfiguration +} + +func NewItemPager( + gs graph.Servicer, + driveID, link string, + fields []string, +) *driveItemPager { + pageCount := pageSize + requestConfig := &msdrives.ItemRootDeltaRequestBuilderGetRequestConfiguration{ + QueryParameters: &msdrives.ItemRootDeltaRequestBuilderGetQueryParameters{ + Top: &pageCount, + Select: fields, + }, + } + + res := &driveItemPager{ + gs: gs, + options: requestConfig, + builder: gs.Client().DrivesById(driveID).Root().Delta(), + } + + if len(link) > 0 { + res.builder = msdrives.NewItemRootDeltaRequestBuilder(link, gs.Adapter()) + } + + return res +} + +func (p *driveItemPager) GetPage(ctx context.Context) (api.DeltaPageLinker, error) { + return p.builder.Get(ctx, p.options) +} + +func (p *driveItemPager) SetNext(link string) { + p.builder = msdrives.NewItemRootDeltaRequestBuilder(link, p.gs.Adapter()) +} + +func (p *driveItemPager) ValuesIn(l api.DeltaPageLinker) ([]models.DriveItemable, error) { + return getValues[models.DriveItemable](l) +} + type userDrivePager struct { gs graph.Servicer builder *msusers.ItemDrivesRequestBuilder @@ -47,15 +107,7 @@ func (p *userDrivePager) SetNext(link string) { } func (p *userDrivePager) ValuesIn(l api.PageLinker) ([]models.Driveable, error) { - page, ok := l.(interface{ GetValue() []models.Driveable }) - if !ok { - return nil, errors.Errorf( - "response of type [%T] does not comply with GetValue() interface", - l, - ) - } - - return page.GetValue(), nil + return getValues[models.Driveable](l) } type siteDrivePager struct { @@ -93,13 +145,5 @@ func (p *siteDrivePager) SetNext(link string) { } func (p *siteDrivePager) ValuesIn(l api.PageLinker) ([]models.Driveable, error) { - page, ok := l.(interface{ GetValue() []models.Driveable }) - if !ok { - return nil, errors.Errorf( - "response of type [%T] does not comply with GetValue() interface", - l, - ) - } - - return page.GetValue(), nil + return getValues[models.Driveable](l) } diff --git a/src/internal/connector/onedrive/collection.go b/src/internal/connector/onedrive/collection.go index a786de0ab..343a8911e 100644 --- a/src/internal/connector/onedrive/collection.go +++ b/src/internal/connector/onedrive/collection.go @@ -5,6 +5,7 @@ import ( "context" "io" "net/http" + "strings" "sync" "sync/atomic" "time" @@ -34,6 +35,10 @@ const ( // Max number of retries to get doc from M365 // Seems to timeout at times because of multiple requests maxRetries = 4 // 1 + 3 retries + + MetaFileSuffix = ".meta" + DirMetaFileSuffix = ".dirmeta" + DataFileSuffix = ".data" ) var ( @@ -56,12 +61,13 @@ type Collection struct { // M365 IDs of file items within this collection driveItems map[string]models.DriveItemable // M365 ID of the drive this collection was created from - driveID string - source driveSource - service graph.Servicer - statusUpdater support.StatusUpdater - itemReader itemReaderFunc - ctrl control.Options + driveID string + source driveSource + service graph.Servicer + statusUpdater support.StatusUpdater + itemReader itemReaderFunc + itemMetaReader itemMetaReaderFunc + ctrl control.Options // should only be true if the old delta token expired doNotMergeItems bool @@ -73,6 +79,15 @@ type itemReaderFunc func( item models.DriveItemable, ) (itemInfo details.ItemInfo, itemData io.ReadCloser, err error) +// itemMetaReaderFunc returns a reader for the metadata of the +// specified item +type itemMetaReaderFunc func( + ctx context.Context, + service graph.Servicer, + driveID string, + item models.DriveItemable, +) (io.ReadCloser, int, error) + // NewCollection creates a Collection func NewCollection( itemClient *http.Client, @@ -101,6 +116,7 @@ func NewCollection( c.itemReader = sharePointItemReader default: c.itemReader = oneDriveItemReader + c.itemMetaReader = oneDriveItemMetaReader } return c @@ -138,6 +154,21 @@ func (oc Collection) DoNotMergeItems() bool { return oc.doNotMergeItems } +// FilePermission is used to store permissions of a specific user to a +// OneDrive item. +type UserPermission struct { + ID string `json:"id,omitempty"` + Roles []string `json:"role,omitempty"` + Email string `json:"email,omitempty"` + Expiration *time.Time `json:"expiration,omitempty"` +} + +// ItemMeta contains metadata about the Item. It gets stored in a +// separate file in kopia +type Metadata struct { + Permissions []UserPermission `json:"permissions,omitempty"` +} + // Item represents a single item retrieved from OneDrive type Item struct { id string @@ -173,18 +204,21 @@ func (od *Item) ModTime() time.Time { // and uses the collection `itemReader` to read the item func (oc *Collection) populateItems(ctx context.Context) { var ( - errs error - byteCount int64 - itemsRead int64 - wg sync.WaitGroup - m sync.Mutex + errs error + byteCount int64 + itemsRead int64 + dirsRead int64 + itemsFound int64 + dirsFound int64 + wg sync.WaitGroup + m sync.Mutex ) // Retrieve the OneDrive folder path to set later in // `details.OneDriveInfo` parentPathString, err := path.GetDriveFolderPath(oc.folderPath) if err != nil { - oc.reportAsCompleted(ctx, 0, 0, err) + oc.reportAsCompleted(ctx, 0, 0, 0, err) return } @@ -205,16 +239,11 @@ func (oc *Collection) populateItems(ctx context.Context) { m.Unlock() } - for id, item := range oc.driveItems { + for _, item := range oc.driveItems { if oc.ctrl.FailFast && errs != nil { break } - if item == nil { - errUpdater(id, errors.New("nil item")) - continue - } - semaphoreCh <- struct{}{} wg.Add(1) @@ -223,13 +252,64 @@ func (oc *Collection) populateItems(ctx context.Context) { defer wg.Done() defer func() { <-semaphoreCh }() + // Read the item var ( - itemID = *item.GetId() - itemName = *item.GetName() - itemSize = *item.GetSize() - itemInfo details.ItemInfo + itemID = *item.GetId() + itemName = *item.GetName() + itemSize = *item.GetSize() + itemInfo details.ItemInfo + itemMeta io.ReadCloser + itemMetaSize int + metaSuffix string + err error ) + isFile := item.GetFile() != nil + + if isFile { + atomic.AddInt64(&itemsFound, 1) + + metaSuffix = MetaFileSuffix + } else { + atomic.AddInt64(&dirsFound, 1) + + metaSuffix = DirMetaFileSuffix + } + + if oc.source == OneDriveSource { + // Fetch metadata for the file + for i := 1; i <= maxRetries; i++ { + if !oc.ctrl.ToggleFeatures.EnablePermissionsBackup { + // We are still writing the metadata file but with + // empty permissions as we don't have a way to + // signify that the permissions was explicitly + // not added. + itemMeta = io.NopCloser(strings.NewReader("{}")) + itemMetaSize = 2 + + break + } + + itemMeta, itemMetaSize, err = oc.itemMetaReader(ctx, oc.service, oc.driveID, item) + + // retry on Timeout type errors, break otherwise. + if err == nil || + !graph.IsErrTimeout(err) || + !graph.IsInternalServerError(err) { + break + } + + if i < maxRetries { + time.Sleep(1 * time.Second) + } + } + + if err != nil { + errUpdater(*item.GetId(), errors.Wrap(err, "failed to get item permissions")) + return + } + } + switch oc.source { case SharePointSource: itemInfo.SharePoint = sharePointItemInfo(item, itemSize) @@ -239,101 +319,127 @@ func (oc *Collection) populateItems(ctx context.Context) { itemInfo.OneDrive.ParentPath = parentPathString } - // Construct a new lazy readCloser to feed to the collection consumer. - // This ensures that downloads won't be attempted unless that consumer - // attempts to read bytes. Assumption is that kopia will check things - // like file modtimes before attempting to read. - itemReader := lazy.NewLazyReadCloser(func() (io.ReadCloser, error) { - // Read the item - var ( - itemData io.ReadCloser - err error - ) + if isFile { + dataSuffix := "" + if oc.source == OneDriveSource { + dataSuffix = DataFileSuffix + } - for i := 1; i <= maxRetries; i++ { - _, itemData, err = oc.itemReader(oc.itemClient, item) - if err == nil { - break - } + // Construct a new lazy readCloser to feed to the collection consumer. + // This ensures that downloads won't be attempted unless that consumer + // attempts to read bytes. Assumption is that kopia will check things + // like file modtimes before attempting to read. + itemReader := lazy.NewLazyReadCloser(func() (io.ReadCloser, error) { + // Read the item + var ( + itemData io.ReadCloser + err error + ) - if graph.IsErrUnauthorized(err) { - // assume unauthorized requests are a sign of an expired - // jwt token, and that we've overrun the available window - // to download the actual file. Re-downloading the item - // will refresh that download url. - di, diErr := getDriveItem(ctx, oc.service, oc.driveID, itemID) - if diErr != nil { - err = errors.Wrap(diErr, "retrieving expired item") + for i := 1; i <= maxRetries; i++ { + _, itemData, err = oc.itemReader(oc.itemClient, item) + if err == nil { break } - item = di + if graph.IsErrUnauthorized(err) { + // assume unauthorized requests are a sign of an expired + // jwt token, and that we've overrun the available window + // to download the actual file. Re-downloading the item + // will refresh that download url. + di, diErr := getDriveItem(ctx, oc.service, oc.driveID, itemID) + if diErr != nil { + err = errors.Wrap(diErr, "retrieving expired item") + break + } - continue + item = di - } else if !graph.IsErrTimeout(err) && !graph.IsErrThrottled(err) && !graph.IsSericeUnavailable(err) { - // TODO: graphAPI will provides headers that state the duration to wait - // in order to succeed again. The one second sleep won't cut it here. - // - // for all non-timeout, non-unauth, non-throttling errors, do not retry - break + continue + + } else if !graph.IsErrTimeout(err) && + !graph.IsInternalServerError(err) { + // Don't retry for non-timeout, on-unauth, as + // we are already retrying it in the default + // retry middleware + break + } + + if i < maxRetries { + time.Sleep(1 * time.Second) + } } - if i < maxRetries { - time.Sleep(1 * time.Second) + // check for errors following retries + if err != nil { + errUpdater(itemID, err) + return nil, err } + + // display/log the item download + progReader, closer := observe.ItemProgress( + ctx, + itemData, + observe.ItemBackupMsg, + observe.PII(itemName+dataSuffix), + itemSize, + ) + go closer() + + return progReader, nil + }) + + oc.data <- &Item{ + id: itemName + dataSuffix, + data: itemReader, + info: itemInfo, } + } - // check for errors following retries - if err != nil { - errUpdater(itemID, err) - return nil, err + if oc.source == OneDriveSource { + metaReader := lazy.NewLazyReadCloser(func() (io.ReadCloser, error) { + progReader, closer := observe.ItemProgress( + ctx, itemMeta, observe.ItemBackupMsg, + observe.PII(itemName+metaSuffix), int64(itemMetaSize)) + go closer() + return progReader, nil + }) + + oc.data <- &Item{ + id: itemName + metaSuffix, + data: metaReader, + info: itemInfo, } + } - // display/log the item download - progReader, closer := observe.ItemProgress(ctx, itemData, observe.ItemBackupMsg, observe.PII(itemName), itemSize) - go closer() - - return progReader, nil - }) - - // This can cause inaccurate counts. Right now it counts all the items - // we intend to read. Errors within the lazy readCloser will create a - // conflict: an item is both successful and erroneous. But the async - // control to fix that is more error-prone than helpful. - // - // TODO: transform this into a stats bus so that async control of stats - // aggregation is handled at the backup level, not at the item iteration - // level. - // // Item read successfully, add to collection - atomic.AddInt64(&itemsRead, 1) + if isFile { + atomic.AddInt64(&itemsRead, 1) + } else { + atomic.AddInt64(&dirsRead, 1) + } + // byteCount iteration atomic.AddInt64(&byteCount, itemSize) - oc.data <- &Item{ - id: itemName, - data: itemReader, - info: itemInfo, - } folderProgress <- struct{}{} }(item) } wg.Wait() - oc.reportAsCompleted(ctx, int(itemsRead), byteCount, errs) + oc.reportAsCompleted(ctx, int(itemsFound), int(itemsRead), byteCount, errs) } -func (oc *Collection) reportAsCompleted(ctx context.Context, itemsRead int, byteCount int64, errs error) { +func (oc *Collection) reportAsCompleted(ctx context.Context, itemsFound, itemsRead int, byteCount int64, errs error) { close(oc.data) status := support.CreateStatus(ctx, support.Backup, 1, // num folders (always 1) support.CollectionMetrics{ - Objects: len(oc.driveItems), // items to read, - Successes: itemsRead, // items read successfully, - TotalBytes: byteCount, // Number of bytes read in the operation, + Objects: itemsFound, // items to read, + Successes: itemsRead, // items read successfully, + TotalBytes: byteCount, // Number of bytes read in the operation, }, errs, oc.folderPath.Folder(), // Additional details diff --git a/src/internal/connector/onedrive/collection_test.go b/src/internal/connector/onedrive/collection_test.go index b608e9068..734009d72 100644 --- a/src/internal/connector/onedrive/collection_test.go +++ b/src/internal/connector/onedrive/collection_test.go @@ -2,8 +2,11 @@ package onedrive import ( "bytes" + "context" + "encoding/json" "io" "net/http" + "strings" "sync" "testing" "time" @@ -60,6 +63,14 @@ func (suite *CollectionUnitTestSuite) TestCollection() { testItemName = "itemName" testItemData = []byte("testdata") now = time.Now() + testItemMeta = Metadata{Permissions: []UserPermission{ + { + ID: "testMetaID", + Roles: []string{"read", "write"}, + Email: "email@provider.com", + Expiration: &now, + }, + }} ) type nst struct { @@ -157,13 +168,14 @@ func (suite *CollectionUnitTestSuite) TestCollection() { suite, suite.testStatusUpdater(&wg, &collStatus), test.source, - control.Options{}) + control.Options{ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}}) require.NotNil(t, coll) assert.Equal(t, folderPath, coll.FullPath()) // Set a item reader, add an item and validate we get the item back mockItem := models.NewDriveItem() mockItem.SetId(&testItemID) + mockItem.SetFile(models.NewFile()) mockItem.SetName(&test.itemDeets.name) mockItem.SetSize(&test.itemDeets.size) mockItem.SetCreatedDateTime(&test.itemDeets.time) @@ -174,6 +186,18 @@ func (suite *CollectionUnitTestSuite) TestCollection() { } coll.itemReader = test.itemReader + coll.itemMetaReader = func(_ context.Context, + _ graph.Servicer, + _ string, + _ models.DriveItemable, + ) (io.ReadCloser, int, error) { + metaJSON, err := json.Marshal(testItemMeta) + if err != nil { + return nil, 0, err + } + + return io.NopCloser(bytes.NewReader(metaJSON)), len(metaJSON), nil + } // Read items from the collection wg.Add(1) @@ -184,28 +208,54 @@ func (suite *CollectionUnitTestSuite) TestCollection() { wg.Wait() + if test.source == OneDriveSource { + require.Len(t, readItems, 2) // .data and .meta + } else { + require.Len(t, readItems, 1) + } + + // Expect only 1 item + require.Equal(t, 1, collStatus.ObjectCount) + require.Equal(t, 1, collStatus.Successful) + // Validate item info and data readItem := readItems[0] readItemInfo := readItem.(data.StreamInfo) - readData, err := io.ReadAll(readItem.ToReader()) - require.NoError(t, err) - assert.Equal(t, testItemData, readData) - - // Expect only 1 item - require.Len(t, readItems, 1) - require.Equal(t, 1, collStatus.ObjectCount, "items iterated") - require.Equal(t, 1, collStatus.Successful, "items successful") - - assert.Equal(t, testItemName, readItem.UUID()) + if test.source == OneDriveSource { + assert.Equal(t, testItemName+DataFileSuffix, readItem.UUID()) + } else { + assert.Equal(t, testItemName, readItem.UUID()) + } require.Implements(t, (*data.StreamModTime)(nil), readItem) mt := readItem.(data.StreamModTime) assert.Equal(t, now, mt.ModTime()) + readData, err := io.ReadAll(readItem.ToReader()) + require.NoError(t, err) + name, parentPath := test.infoFrom(t, readItemInfo.Info()) + + assert.Equal(t, testItemData, readData) assert.Equal(t, testItemName, name) assert.Equal(t, driveFolderPath, parentPath) + + if test.source == OneDriveSource { + readItemMeta := readItems[1] + + assert.Equal(t, testItemName+MetaFileSuffix, readItemMeta.UUID()) + + readMetaData, err := io.ReadAll(readItemMeta.ToReader()) + require.NoError(t, err) + + tm, err := json.Marshal(testItemMeta) + if err != nil { + t.Fatal("unable to marshall test permissions", err) + } + + assert.Equal(t, tm, readMetaData) + } }) } } @@ -251,10 +301,11 @@ func (suite *CollectionUnitTestSuite) TestCollectionReadError() { suite, suite.testStatusUpdater(&wg, &collStatus), test.source, - control.Options{}) + control.Options{ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}}) mockItem := models.NewDriveItem() mockItem.SetId(&testItemID) + mockItem.SetFile(models.NewFile()) mockItem.SetName(&name) mockItem.SetSize(&size) mockItem.SetCreatedDateTime(&now) @@ -265,6 +316,14 @@ func (suite *CollectionUnitTestSuite) TestCollectionReadError() { return details.ItemInfo{}, nil, assert.AnError } + coll.itemMetaReader = func(_ context.Context, + _ graph.Servicer, + _ string, + _ models.DriveItemable, + ) (io.ReadCloser, int, error) { + return io.NopCloser(strings.NewReader(`{}`)), 2, nil + } + collItem, ok := <-coll.Items() assert.True(t, ok) @@ -279,3 +338,87 @@ func (suite *CollectionUnitTestSuite) TestCollectionReadError() { }) } } + +func (suite *CollectionUnitTestSuite) TestCollectionDisablePermissionsBackup() { + table := []struct { + name string + source driveSource + }{ + { + name: "oneDrive", + source: OneDriveSource, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + var ( + testItemID = "fakeItemID" + testItemName = "Fake Item" + testItemSize = int64(10) + + collStatus = support.ConnectorOperationStatus{} + wg = sync.WaitGroup{} + ) + + wg.Add(1) + + folderPath, err := GetCanonicalPath("drive/driveID1/root:/folderPath", "a-tenant", "a-user", test.source) + require.NoError(t, err) + + coll := NewCollection( + graph.HTTPClient(graph.NoTimeout()), + folderPath, + "fakeDriveID", + suite, + suite.testStatusUpdater(&wg, &collStatus), + test.source, + control.Options{ToggleFeatures: control.Toggles{}}) + + now := time.Now() + mockItem := models.NewDriveItem() + mockItem.SetFile(models.NewFile()) + mockItem.SetId(&testItemID) + mockItem.SetName(&testItemName) + mockItem.SetSize(&testItemSize) + mockItem.SetCreatedDateTime(&now) + mockItem.SetLastModifiedDateTime(&now) + coll.Add(mockItem) + + coll.itemReader = func( + *http.Client, + models.DriveItemable, + ) (details.ItemInfo, io.ReadCloser, error) { + return details.ItemInfo{OneDrive: &details.OneDriveInfo{ItemName: "fakeName", Modified: time.Now()}}, + io.NopCloser(strings.NewReader("Fake Data!")), + nil + } + + coll.itemMetaReader = func(_ context.Context, + _ graph.Servicer, + _ string, + _ models.DriveItemable, + ) (io.ReadCloser, int, error) { + return io.NopCloser(strings.NewReader(`{"key": "value"}`)), 16, nil + } + + readItems := []data.Stream{} + for item := range coll.Items() { + readItems = append(readItems, item) + } + + wg.Wait() + + // Expect no items + require.Equal(t, 1, collStatus.ObjectCount) + require.Equal(t, 1, collStatus.Successful) + + for _, i := range readItems { + if strings.HasSuffix(i.UUID(), MetaFileSuffix) { + content, err := io.ReadAll(i.ToReader()) + require.NoError(t, err) + require.Equal(t, content, []byte("{}")) + } + } + }) + } +} diff --git a/src/internal/connector/onedrive/collections.go b/src/internal/connector/onedrive/collections.go index 0813c13ed..50c5323d9 100644 --- a/src/internal/connector/onedrive/collections.go +++ b/src/internal/connector/onedrive/collections.go @@ -2,7 +2,9 @@ package onedrive import ( "context" + "encoding/json" "fmt" + "io" "net/http" "strings" @@ -63,6 +65,19 @@ type Collections struct { // for a OneDrive folder CollectionMap map[string]data.Collection + // Not the most ideal, but allows us to change the pager function for testing + // as needed. This will allow us to mock out some scenarios during testing. + drivePagerFunc func( + source driveSource, + servicer graph.Servicer, + resourceOwner string, + fields []string, + ) (drivePager, error) + itemPagerFunc func( + servicer graph.Servicer, + driveID, link string, + ) itemPager + // Track stats from drive enumeration. Represents the items backed up. NumItems int NumFiles int @@ -80,31 +95,178 @@ func NewCollections( ctrlOpts control.Options, ) *Collections { return &Collections{ - itemClient: itemClient, - tenant: tenant, - resourceOwner: resourceOwner, - source: source, - matcher: matcher, - CollectionMap: map[string]data.Collection{}, - service: service, - statusUpdater: statusUpdater, - ctrl: ctrlOpts, + itemClient: itemClient, + tenant: tenant, + resourceOwner: resourceOwner, + source: source, + matcher: matcher, + CollectionMap: map[string]data.Collection{}, + drivePagerFunc: PagerForSource, + itemPagerFunc: defaultItemPager, + service: service, + statusUpdater: statusUpdater, + ctrl: ctrlOpts, } } -// Retrieves drive data as set of `data.Collections` -func (c *Collections) Get(ctx context.Context) ([]data.Collection, error) { - // Enumerate drives for the specified resourceOwner - pager, err := PagerForSource(c.source, c.service, c.resourceOwner, nil) +func deserializeMetadata( + ctx context.Context, + cols []data.Collection, +) (map[string]string, map[string]map[string]string, error) { + logger.Ctx(ctx).Infow( + "deserialzing previous backup metadata", + "num_collections", + len(cols), + ) + + prevDeltas := map[string]string{} + prevFolders := map[string]map[string]string{} + + for _, col := range cols { + items := col.Items() + + for breakLoop := false; !breakLoop; { + select { + case <-ctx.Done(): + return nil, nil, errors.Wrap(ctx.Err(), "deserialzing previous backup metadata") + + case item, ok := <-items: + if !ok { + // End of collection items. + breakLoop = true + break + } + + var err error + + switch item.UUID() { + case graph.PreviousPathFileName: + err = deserializeMap(item.ToReader(), prevFolders) + + case graph.DeltaURLsFileName: + err = deserializeMap(item.ToReader(), prevDeltas) + + default: + logger.Ctx(ctx).Infow( + "skipping unknown metadata file", + "file_name", + item.UUID(), + ) + + continue + } + + if err == nil { + // Successful decode. + continue + } + + // This is conservative, but report an error if any of the items for + // any of the deserialized maps have duplicate drive IDs. This will + // cause the entire backup to fail, but it's not clear if higher + // layers would have caught this. Worst case if we don't handle this + // we end up in a situation where we're sourcing items from the wrong + // base in kopia wrapper. + if errors.Is(err, errExistingMapping) { + return nil, nil, errors.Wrapf( + err, + "deserializing metadata file %s", + item.UUID(), + ) + } + + logger.Ctx(ctx).Errorw( + "deserializing base backup metadata. Falling back to full backup for selected drives", + "error", + err, + "file_name", + item.UUID(), + ) + } + } + + // Go through and remove partial results (i.e. path mapping but no delta URL + // or vice-versa). + for k, v := range prevDeltas { + // Remove entries with an empty delta token as it's not useful. + if len(v) == 0 { + delete(prevDeltas, k) + delete(prevFolders, k) + } + + // Remove entries without a folders map as we can't tell kopia the + // hierarchy changes. + if _, ok := prevFolders[k]; !ok { + delete(prevDeltas, k) + } + } + + for k := range prevFolders { + if _, ok := prevDeltas[k]; !ok { + delete(prevFolders, k) + } + } + } + + return prevDeltas, prevFolders, nil +} + +var errExistingMapping = errors.New("mapping already exists for same drive ID") + +// deserializeMap takes an reader and a map of already deserialized items and +// adds the newly deserialized items to alreadyFound. Items are only added to +// alreadyFound if none of the keys in the freshly deserialized map already +// exist in alreadyFound. reader is closed at the end of this function. +func deserializeMap[T any](reader io.ReadCloser, alreadyFound map[string]T) error { + defer reader.Close() + + tmp := map[string]T{} + + err := json.NewDecoder(reader).Decode(&tmp) if err != nil { - return nil, err + return errors.Wrap(err, "deserializing file contents") + } + + var duplicate bool + + for k := range tmp { + if _, ok := alreadyFound[k]; ok { + duplicate = true + break + } + } + + if duplicate { + return errors.WithStack(errExistingMapping) + } + + maps.Copy(alreadyFound, tmp) + + return nil +} + +// Retrieves drive data as set of `data.Collections` and a set of item names to +// be excluded from the upcoming backup. +func (c *Collections) Get( + ctx context.Context, + prevMetadata []data.Collection, +) ([]data.Collection, map[string]struct{}, error) { + _, _, err := deserializeMetadata(ctx, prevMetadata) + if err != nil { + return nil, nil, err + } + + // Enumerate drives for the specified resourceOwner + pager, err := c.drivePagerFunc(c.source, c.service, c.resourceOwner, nil) + if err != nil { + return nil, nil, err } retry := c.source == OneDriveSource drives, err := drives(ctx, pager, retry) if err != nil { - return nil, err + return nil, nil, err } var ( @@ -127,26 +289,34 @@ func (c *Collections) Get(ctx context.Context) ([]data.Collection, error) { delta, paths, excluded, err := collectItems( ctx, - c.service, + c.itemPagerFunc( + c.service, + driveID, + "", + ), driveID, driveName, c.UpdateCollections, ) if err != nil { - return nil, err + return nil, nil, err } + // It's alright to have an empty folders map (i.e. no folders found) but not + // an empty delta token. This is because when deserializing the metadata we + // remove entries for which there is no corresponding delta token/folder. If + // we leave empty delta tokens then we may end up setting the State field + // for collections when not actually getting delta results. if len(delta) > 0 { deltaURLs[driveID] = delta } - if len(paths) > 0 { - folderPaths[driveID] = map[string]string{} - - for id, p := range paths { - folderPaths[driveID][id] = p - } - } + // Avoid the edge case where there's no paths but we do have a valid delta + // token. We can accomplish this by adding an empty paths map for this + // drive. If we don't have this then the next backup won't use the delta + // token because it thinks the folder paths weren't persisted. + folderPaths[driveID] = map[string]string{} + maps.Copy(folderPaths[driveID], paths) maps.Copy(excludedItems, excluded) } @@ -185,7 +355,8 @@ func (c *Collections) Get(ctx context.Context) ([]data.Collection, error) { collections = append(collections, metadata) } - return collections, nil + // TODO(ashmrtn): Track and return the set of items to exclude. + return collections, nil, nil } // UpdateCollections initializes and adds the provided drive items to Collections @@ -259,6 +430,12 @@ func (c *Collections) UpdateCollections( // already created and partially populated. updatePath(newPaths, *item.GetId(), folderPath.String()) + if c.source != OneDriveSource { + continue + } + + fallthrough + case item.GetFile() != nil: if item.GetDeleted() != nil { excluded[*item.GetId()] = struct{}{} @@ -274,6 +451,7 @@ func (c *Collections) UpdateCollections( // the exclude list. col, found := c.CollectionMap[collectionPath.String()] + if !found { // TODO(ashmrtn): Compare old and new path and set collection state // accordingly. @@ -288,13 +466,17 @@ func (c *Collections) UpdateCollections( c.CollectionMap[collectionPath.String()] = col c.NumContainers++ - c.NumItems++ } collection := col.(*Collection) collection.Add(item) - c.NumFiles++ + c.NumItems++ + if item.GetFile() != nil { + // This is necessary as we have a fallthrough for + // folders and packages + c.NumFiles++ + } default: return errors.Errorf("item type not supported. item name : %s", *item.GetName()) diff --git a/src/internal/connector/onedrive/collections_test.go b/src/internal/connector/onedrive/collections_test.go index b69253918..f784bad62 100644 --- a/src/internal/connector/onedrive/collections_test.go +++ b/src/internal/connector/onedrive/collections_test.go @@ -1,9 +1,11 @@ package onedrive import ( + "context" "strings" "testing" + "github.com/google/uuid" "github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -11,8 +13,12 @@ import ( "golang.org/x/exp/maps" "github.com/alcionai/corso/src/internal/connector/graph" + gapi "github.com/alcionai/corso/src/internal/connector/graph/api" + "github.com/alcionai/corso/src/internal/connector/support" + "github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/pkg/control" + "github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/selectors" ) @@ -133,7 +139,7 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { user, testBaseDrivePath, ), - expectedItemCount: 2, + expectedItemCount: 1, expectedFileCount: 1, expectedContainerCount: 1, // Root folder is skipped since it's always present. @@ -145,10 +151,15 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { items: []models.DriveItemable{ driveItem("folder", "folder", testBaseDrivePath, false, true, false), }, - inputFolderMap: map[string]string{}, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, + inputFolderMap: map[string]string{}, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), expectedMetadataPaths: map[string]string{ "folder": expectedPathAsSlice( suite.T(), @@ -157,17 +168,24 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/folder", )[0], }, - expectedExcludes: map[string]struct{}{}, + expectedItemCount: 1, + expectedContainerCount: 1, + expectedExcludes: map[string]struct{}{}, }, { testCase: "Single Package", items: []models.DriveItemable{ driveItem("package", "package", testBaseDrivePath, false, false, true), }, - inputFolderMap: map[string]string{}, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, + inputFolderMap: map[string]string{}, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), expectedMetadataPaths: map[string]string{ "package": expectedPathAsSlice( suite.T(), @@ -176,7 +194,9 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/package", )[0], }, - expectedExcludes: map[string]struct{}{}, + expectedItemCount: 1, + expectedContainerCount: 1, + expectedExcludes: map[string]struct{}{}, }, { testCase: "1 root file, 1 folder, 1 package, 2 files, 3 collections", @@ -198,7 +218,7 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+folder, testBaseDrivePath+pkg, ), - expectedItemCount: 6, + expectedItemCount: 5, expectedFileCount: 3, expectedContainerCount: 3, expectedMetadataPaths: map[string]string{ @@ -232,23 +252,17 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { inputFolderMap: map[string]string{}, scope: (&selectors.OneDriveBackup{}).Folders([]string{"folder"})[0], expect: assert.NoError, - expectedCollectionPaths: append( - expectedPathAsSlice( - suite.T(), - tenant, - user, - testBaseDrivePath+"/folder", - ), - expectedPathAsSlice( - suite.T(), - tenant, - user, - testBaseDrivePath+folderSub+folder, - )..., + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath+"/folder", + testBaseDrivePath+folderSub, + testBaseDrivePath+folderSub+folder, ), expectedItemCount: 4, expectedFileCount: 2, - expectedContainerCount: 2, + expectedContainerCount: 3, // just "folder" isn't added here because the include check is done on the // parent path since we only check later if something is a folder or not. expectedMetadataPaths: map[string]string{ @@ -287,11 +301,12 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { suite.T(), tenant, user, + testBaseDrivePath+folderSub, testBaseDrivePath+folderSub+folder, ), expectedItemCount: 2, expectedFileCount: 1, - expectedContainerCount: 1, + expectedContainerCount: 2, expectedMetadataPaths: map[string]string{ "folder2": expectedPathAsSlice( suite.T(), @@ -322,7 +337,7 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { user, testBaseDrivePath+folderSub, ), - expectedItemCount: 2, + expectedItemCount: 1, expectedFileCount: 1, expectedContainerCount: 1, // No child folders for subfolder so nothing here. @@ -348,12 +363,17 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/folder/subfolder", )[0], }, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, - expectedItemCount: 0, - expectedFileCount: 0, - expectedContainerCount: 0, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), + expectedItemCount: 1, + expectedFileCount: 0, + expectedContainerCount: 1, expectedMetadataPaths: map[string]string{ "folder": expectedPathAsSlice( suite.T(), @@ -389,12 +409,17 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/a-folder/subfolder", )[0], }, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, - expectedItemCount: 0, - expectedFileCount: 0, - expectedContainerCount: 0, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), + expectedItemCount: 1, + expectedFileCount: 0, + expectedContainerCount: 1, expectedMetadataPaths: map[string]string{ "folder": expectedPathAsSlice( suite.T(), @@ -431,12 +456,17 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/a-folder/subfolder", )[0], }, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, - expectedItemCount: 0, - expectedFileCount: 0, - expectedContainerCount: 0, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), + expectedItemCount: 2, + expectedFileCount: 0, + expectedContainerCount: 1, expectedMetadataPaths: map[string]string{ "folder": expectedPathAsSlice( suite.T(), @@ -473,12 +503,17 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/a-folder/subfolder", )[0], }, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, - expectedItemCount: 0, - expectedFileCount: 0, - expectedContainerCount: 0, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), + expectedItemCount: 2, + expectedFileCount: 0, + expectedContainerCount: 1, expectedMetadataPaths: map[string]string{ "folder": expectedPathAsSlice( suite.T(), @@ -544,12 +579,17 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testBaseDrivePath+"/folder/subfolder", )[0], }, - scope: anyFolder, - expect: assert.NoError, - expectedCollectionPaths: []string{}, - expectedItemCount: 0, - expectedFileCount: 0, - expectedContainerCount: 0, + scope: anyFolder, + expect: assert.NoError, + expectedCollectionPaths: expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + ), + expectedItemCount: 1, + expectedFileCount: 0, + expectedContainerCount: 1, expectedMetadataPaths: map[string]string{ "subfolder": expectedPathAsSlice( suite.T(), @@ -595,7 +635,7 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { testFolderMatcher{tt.scope}, &MockGraphService{}, nil, - control.Options{}) + control.Options{ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}}) err := c.UpdateCollections( ctx, @@ -621,13 +661,787 @@ func (suite *OneDriveCollectionsSuite) TestUpdateCollections() { } } -func driveItem(id string, name string, path string, isFile, isFolder, isPackage bool) models.DriveItemable { +func (suite *OneDriveCollectionsSuite) TestDeserializeMetadata() { + tenant := "a-tenant" + user := "a-user" + driveID1 := "1" + driveID2 := "2" + deltaURL1 := "url/1" + deltaURL2 := "url/2" + + folderID1 := "folder1" + folderID2 := "folder2" + path1 := "folder1/path" + path2 := "folder2/path" + + table := []struct { + name string + // Each function returns the set of files for a single data.Collection. + cols []func() []graph.MetadataCollectionEntry + expectedDeltas map[string]string + expectedPaths map[string]map[string]string + errCheck assert.ErrorAssertionFunc + }{ + { + name: "SuccessOneDriveAllOneCollection", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + } + }, + }, + expectedDeltas: map[string]string{ + driveID1: deltaURL1, + }, + expectedPaths: map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + errCheck: assert.NoError, + }, + { + name: "MissingPaths", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + } + }, + }, + expectedDeltas: map[string]string{}, + expectedPaths: map[string]map[string]string{}, + errCheck: assert.NoError, + }, + { + name: "MissingDeltas", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + } + }, + }, + expectedDeltas: map[string]string{}, + expectedPaths: map[string]map[string]string{}, + errCheck: assert.NoError, + }, + { + // An empty path map but valid delta results in metadata being returned + // since it's possible to have a drive with no folders other than the + // root. + name: "EmptyPaths", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: {}, + }, + ), + } + }, + }, + expectedDeltas: map[string]string{driveID1: deltaURL1}, + expectedPaths: map[string]map[string]string{driveID1: {}}, + errCheck: assert.NoError, + }, + { + // An empty delta map but valid path results in no metadata for that drive + // being returned since the path map is only useful if we have a valid + // delta. + name: "EmptyDeltas", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{ + driveID1: "", + }, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + } + }, + }, + expectedDeltas: map[string]string{}, + expectedPaths: map[string]map[string]string{}, + errCheck: assert.NoError, + }, + { + name: "SuccessTwoDrivesTwoCollections", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + } + }, + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID2: deltaURL2}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID2: { + folderID2: path2, + }, + }, + ), + } + }, + }, + expectedDeltas: map[string]string{ + driveID1: deltaURL1, + driveID2: deltaURL2, + }, + expectedPaths: map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + driveID2: { + folderID2: path2, + }, + }, + errCheck: assert.NoError, + }, + { + // Bad formats are logged but skip adding entries to the maps and don't + // return an error. + name: "BadFormat", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]string{driveID1: deltaURL1}, + ), + } + }, + }, + expectedDeltas: map[string]string{}, + expectedPaths: map[string]map[string]string{}, + errCheck: assert.NoError, + }, + { + // Unexpected files are logged and skipped. They don't cause an error to + // be returned. + name: "BadFileName", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + graph.NewMetadataEntry( + "foo", + map[string]string{driveID1: deltaURL1}, + ), + } + }, + }, + expectedDeltas: map[string]string{ + driveID1: deltaURL1, + }, + expectedPaths: map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + errCheck: assert.NoError, + }, + { + name: "DriveAlreadyFound_Paths", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + } + }, + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID2: path2, + }, + }, + ), + } + }, + }, + expectedDeltas: nil, + expectedPaths: nil, + errCheck: assert.Error, + }, + { + name: "DriveAlreadyFound_Deltas", + cols: []func() []graph.MetadataCollectionEntry{ + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL1}, + ), + graph.NewMetadataEntry( + graph.PreviousPathFileName, + map[string]map[string]string{ + driveID1: { + folderID1: path1, + }, + }, + ), + } + }, + func() []graph.MetadataCollectionEntry { + return []graph.MetadataCollectionEntry{ + graph.NewMetadataEntry( + graph.DeltaURLsFileName, + map[string]string{driveID1: deltaURL2}, + ), + } + }, + }, + expectedDeltas: nil, + expectedPaths: nil, + errCheck: assert.Error, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + ctx, flush := tester.NewContext() + defer flush() + + cols := []data.Collection{} + + for _, c := range test.cols { + mc, err := graph.MakeMetadataCollection( + tenant, + user, + path.OneDriveService, + path.FilesCategory, + c(), + func(*support.ConnectorOperationStatus) {}, + ) + require.NoError(t, err) + + cols = append(cols, mc) + } + + deltas, paths, err := deserializeMetadata(ctx, cols) + test.errCheck(t, err) + + assert.Equal(t, test.expectedDeltas, deltas) + assert.Equal(t, test.expectedPaths, paths) + }) + } +} + +type mockDeltaPageLinker struct { + link *string + delta *string +} + +func (pl *mockDeltaPageLinker) GetOdataNextLink() *string { + return pl.link +} + +func (pl *mockDeltaPageLinker) GetOdataDeltaLink() *string { + return pl.delta +} + +type deltaPagerResult struct { + items []models.DriveItemable + nextLink *string + deltaLink *string + err error +} + +type mockItemPager struct { + // DriveID -> set of return values for queries for that drive. + toReturn []deltaPagerResult + getIdx int +} + +func (p *mockItemPager) GetPage(context.Context) (gapi.DeltaPageLinker, error) { + if len(p.toReturn) <= p.getIdx { + return nil, assert.AnError + } + + idx := p.getIdx + p.getIdx++ + + return &mockDeltaPageLinker{ + p.toReturn[idx].nextLink, + p.toReturn[idx].deltaLink, + }, p.toReturn[idx].err +} + +func (p *mockItemPager) SetNext(string) {} + +func (p *mockItemPager) ValuesIn(gapi.DeltaPageLinker) ([]models.DriveItemable, error) { + idx := p.getIdx + if idx > 0 { + // Return values lag by one since we increment in GetPage(). + idx-- + } + + if len(p.toReturn) <= idx { + return nil, assert.AnError + } + + return p.toReturn[idx].items, nil +} + +func (suite *OneDriveCollectionsSuite) TestGet() { + anyFolder := (&selectors.OneDriveBackup{}).Folders(selectors.Any())[0] + + tenant := "a-tenant" + user := "a-user" + + metadataPath, err := path.Builder{}.ToServiceCategoryMetadataPath( + tenant, + user, + path.OneDriveService, + path.FilesCategory, + false, + ) + require.NoError(suite.T(), err, "making metadata path") + + rootFolderPath := expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + )[0] + folderPath := expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath+"/folder", + )[0] + + empty := "" + next := "next" + delta := "delta1" + delta2 := "delta2" + + driveID1 := uuid.NewString() + drive1 := models.NewDrive() + drive1.SetId(&driveID1) + drive1.SetName(&driveID1) + + driveID2 := uuid.NewString() + drive2 := models.NewDrive() + drive2.SetId(&driveID2) + drive2.SetName(&driveID2) + + driveBasePath2 := "drive/driveID2/root:" + + rootFolderPath2 := expectedPathAsSlice( + suite.T(), + tenant, + user, + driveBasePath2, + )[0] + folderPath2 := expectedPathAsSlice( + suite.T(), + tenant, + user, + driveBasePath2+"/folder", + )[0] + + table := []struct { + name string + drives []models.Driveable + items map[string][]deltaPagerResult + errCheck assert.ErrorAssertionFunc + // Collection name -> set of item IDs. We can't check item data because + // that's not mocked out. Metadata is checked separately. + expectedCollections map[string][]string + expectedDeltaURLs map[string]string + expectedFolderPaths map[string]map[string]string + expectedDelList map[string]struct{} + }{ + { + name: "OneDrive_OneItemPage_DelFileOnly_NoFolders_NoErrors", + drives: []models.Driveable{drive1}, + items: map[string][]deltaPagerResult{ + driveID1: { + { + items: []models.DriveItemable{ + delItem("file", testBaseDrivePath, true, false, false), + }, + deltaLink: &delta, + }, + }, + }, + errCheck: assert.NoError, + expectedCollections: map[string][]string{}, + expectedDeltaURLs: map[string]string{ + driveID1: delta, + }, + expectedFolderPaths: map[string]map[string]string{ + // We need an empty map here so deserializing metadata knows the delta + // token for this drive is valid. + driveID1: {}, + }, + expectedDelList: map[string]struct{}{ + "file": {}, + }, + }, + { + name: "OneDrive_OneItemPage_NoFolders_NoErrors", + drives: []models.Driveable{drive1}, + items: map[string][]deltaPagerResult{ + driveID1: { + { + items: []models.DriveItemable{ + driveItem("file", "file", testBaseDrivePath, true, false, false), + }, + deltaLink: &delta, + }, + }, + }, + errCheck: assert.NoError, + expectedCollections: map[string][]string{ + expectedPathAsSlice( + suite.T(), + tenant, + user, + testBaseDrivePath, + )[0]: {"file"}, + }, + expectedDeltaURLs: map[string]string{ + driveID1: delta, + }, + expectedFolderPaths: map[string]map[string]string{ + // We need an empty map here so deserializing metadata knows the delta + // token for this drive is valid. + driveID1: {}, + }, + expectedDelList: map[string]struct{}{}, + }, + { + name: "OneDrive_OneItemPage_NoErrors", + drives: []models.Driveable{drive1}, + items: map[string][]deltaPagerResult{ + driveID1: { + { + items: []models.DriveItemable{ + driveItem("folder", "folder", testBaseDrivePath, false, true, false), + driveItem("file", "file", testBaseDrivePath+"/folder", true, false, false), + }, + deltaLink: &delta, + }, + }, + }, + errCheck: assert.NoError, + expectedCollections: map[string][]string{ + folderPath: {"file"}, + rootFolderPath: {"folder"}, + }, + expectedDeltaURLs: map[string]string{ + driveID1: delta, + }, + expectedFolderPaths: map[string]map[string]string{ + driveID1: { + "folder": folderPath, + }, + }, + expectedDelList: map[string]struct{}{}, + }, + { + name: "OneDrive_OneItemPage_EmptyDelta_NoErrors", + drives: []models.Driveable{drive1}, + items: map[string][]deltaPagerResult{ + driveID1: { + { + items: []models.DriveItemable{ + driveItem("folder", "folder", testBaseDrivePath, false, true, false), + driveItem("file", "file", testBaseDrivePath+"/folder", true, false, false), + }, + deltaLink: &empty, + }, + }, + }, + errCheck: assert.NoError, + expectedCollections: map[string][]string{ + folderPath: {"file"}, + rootFolderPath: {"folder"}, + }, + expectedDeltaURLs: map[string]string{}, + expectedFolderPaths: map[string]map[string]string{}, + expectedDelList: map[string]struct{}{}, + }, + { + name: "OneDrive_TwoItemPages_NoErrors", + drives: []models.Driveable{drive1}, + items: map[string][]deltaPagerResult{ + driveID1: { + { + items: []models.DriveItemable{ + driveItem("folder", "folder", testBaseDrivePath, false, true, false), + driveItem("file", "file", testBaseDrivePath+"/folder", true, false, false), + }, + nextLink: &next, + }, + { + items: []models.DriveItemable{ + driveItem("folder", "folder", testBaseDrivePath, false, true, false), + driveItem("file2", "file2", testBaseDrivePath+"/folder", true, false, false), + }, + deltaLink: &delta, + }, + }, + }, + errCheck: assert.NoError, + expectedCollections: map[string][]string{ + folderPath: {"file", "file2"}, + rootFolderPath: {"folder"}, + }, + expectedDeltaURLs: map[string]string{ + driveID1: delta, + }, + expectedFolderPaths: map[string]map[string]string{ + driveID1: { + "folder": folderPath, + }, + }, + expectedDelList: map[string]struct{}{}, + }, + { + name: "TwoDrives_OneItemPageEach_NoErrors", + drives: []models.Driveable{ + drive1, + drive2, + }, + items: map[string][]deltaPagerResult{ + driveID1: { + { + items: []models.DriveItemable{ + driveItem("folder", "folder", testBaseDrivePath, false, true, false), + driveItem("file", "file", testBaseDrivePath+"/folder", true, false, false), + }, + deltaLink: &delta, + }, + }, + driveID2: { + { + items: []models.DriveItemable{ + driveItem("folder", "folder", driveBasePath2, false, true, false), + driveItem("file", "file", driveBasePath2+"/folder", true, false, false), + }, + deltaLink: &delta2, + }, + }, + }, + errCheck: assert.NoError, + expectedCollections: map[string][]string{ + folderPath: {"file"}, + folderPath2: {"file"}, + rootFolderPath: {"folder"}, + rootFolderPath2: {"folder"}, + }, + expectedDeltaURLs: map[string]string{ + driveID1: delta, + driveID2: delta2, + }, + expectedFolderPaths: map[string]map[string]string{ + driveID1: { + "folder": folderPath, + }, + driveID2: { + "folder": folderPath2, + }, + }, + expectedDelList: map[string]struct{}{}, + }, + { + name: "OneDrive_OneItemPage_Errors", + drives: []models.Driveable{drive1}, + items: map[string][]deltaPagerResult{ + driveID1: { + { + err: assert.AnError, + }, + }, + }, + errCheck: assert.Error, + expectedCollections: nil, + expectedDeltaURLs: nil, + expectedFolderPaths: nil, + expectedDelList: nil, + }, + } + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + ctx, flush := tester.NewContext() + defer flush() + + drivePagerFunc := func( + source driveSource, + servicer graph.Servicer, + resourceOwner string, + fields []string, + ) (drivePager, error) { + return &mockDrivePager{ + toReturn: []pagerResult{ + { + drives: test.drives, + }, + }, + }, nil + } + + itemPagerFunc := func( + servicer graph.Servicer, + driveID, link string, + ) itemPager { + return &mockItemPager{ + toReturn: test.items[driveID], + } + } + + c := NewCollections( + graph.HTTPClient(graph.NoTimeout()), + tenant, + user, + OneDriveSource, + testFolderMatcher{anyFolder}, + &MockGraphService{}, + func(*support.ConnectorOperationStatus) {}, + control.Options{ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}}, + ) + c.drivePagerFunc = drivePagerFunc + c.itemPagerFunc = itemPagerFunc + + // TODO(ashmrtn): Allow passing previous metadata. + cols, _, err := c.Get(ctx, nil) + test.errCheck(t, err) + + if err != nil { + return + } + + for _, baseCol := range cols { + folderPath := baseCol.FullPath().String() + if folderPath == metadataPath.String() { + deltas, paths, err := deserializeMetadata(ctx, []data.Collection{baseCol}) + if !assert.NoError(t, err, "deserializing metadata") { + continue + } + + assert.Equal(t, test.expectedDeltaURLs, deltas) + assert.Equal(t, test.expectedFolderPaths, paths) + + continue + } + + // TODO(ashmrtn): We should really be getting items in the collection + // via the Items() channel, but we don't have a way to mock out the + // actual item fetch yet (mostly wiring issues). The lack of that makes + // this check a bit more bittle since internal details can change. + col, ok := baseCol.(*Collection) + require.True(t, ok, "getting onedrive.Collection handle") + + itemIDs := make([]string, 0, len(col.driveItems)) + + for id := range col.driveItems { + itemIDs = append(itemIDs, id) + } + + assert.ElementsMatch(t, test.expectedCollections[folderPath], itemIDs) + } + + // TODO(ashmrtn): Uncomment this when we begin return the set of items to + // remove from the upcoming backup. + // assert.Equal(t, test.expectedDelList, delList) + }) + } +} + +func driveItem( + id string, + name string, + parentPath string, + isFile, isFolder, isPackage bool, +) models.DriveItemable { item := models.NewDriveItem() item.SetName(&name) item.SetId(&id) parentReference := models.NewItemReference() - parentReference.SetPath(&path) + parentReference.SetPath(&parentPath) item.SetParentReference(parentReference) switch { @@ -644,13 +1458,17 @@ func driveItem(id string, name string, path string, isFile, isFolder, isPackage // delItem creates a DriveItemable that is marked as deleted. path must be set // to the base drive path. -func delItem(id string, path string, isFile, isFolder, isPackage bool) models.DriveItemable { +func delItem( + id string, + parentPath string, + isFile, isFolder, isPackage bool, +) models.DriveItemable { item := models.NewDriveItem() item.SetId(&id) item.SetDeleted(models.NewDeleted()) parentReference := models.NewItemReference() - parentReference.SetPath(&path) + parentReference.SetPath(&parentPath) item.SetParentReference(parentReference) switch { diff --git a/src/internal/connector/onedrive/drive.go b/src/internal/connector/onedrive/drive.go index 9680812b8..d1efece5c 100644 --- a/src/internal/connector/onedrive/drive.go +++ b/src/internal/connector/onedrive/drive.go @@ -6,7 +6,6 @@ import ( "strings" msdrive "github.com/microsoftgraph/msgraph-sdk-go/drive" - msdrives "github.com/microsoftgraph/msgraph-sdk-go/drives" "github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors" "github.com/pkg/errors" @@ -135,11 +134,42 @@ type itemCollector func( excluded map[string]struct{}, ) error +type itemPager interface { + GetPage(context.Context) (gapi.DeltaPageLinker, error) + SetNext(nextLink string) + ValuesIn(gapi.DeltaPageLinker) ([]models.DriveItemable, error) +} + +func defaultItemPager( + servicer graph.Servicer, + driveID, link string, +) itemPager { + return api.NewItemPager( + servicer, + driveID, + link, + []string{ + "content.downloadUrl", + "createdBy", + "createdDateTime", + "file", + "folder", + "id", + "lastModifiedDateTime", + "name", + "package", + "parentReference", + "root", + "size", + }, + ) +} + // collectItems will enumerate all items in the specified drive and hand them to the // provided `collector` method func collectItems( ctx context.Context, - service graph.Servicer, + pager itemPager, driveID, driveName string, collector itemCollector, ) (string, map[string]string, map[string]struct{}, error) { @@ -154,34 +184,8 @@ func collectItems( maps.Copy(newPaths, oldPaths) - // TODO: Specify a timestamp in the delta query - // https://docs.microsoft.com/en-us/graph/api/driveitem-delta? - // view=graph-rest-1.0&tabs=http#example-4-retrieving-delta-results-using-a-timestamp - builder := service.Client().DrivesById(driveID).Root().Delta() - pageCount := int32(999) // max we can do is 999 - requestFields := []string{ - "content.downloadUrl", - "createdBy", - "createdDateTime", - "file", - "folder", - "id", - "lastModifiedDateTime", - "name", - "package", - "parentReference", - "root", - "size", - } - requestConfig := &msdrives.ItemRootDeltaRequestBuilderGetRequestConfiguration{ - QueryParameters: &msdrives.ItemRootDeltaRequestBuilderGetQueryParameters{ - Top: &pageCount, - Select: requestFields, - }, - } - for { - r, err := builder.Get(ctx, requestConfig) + page, err := pager.GetPage(ctx) if err != nil { return "", nil, nil, errors.Wrapf( err, @@ -190,23 +194,29 @@ func collectItems( ) } - err = collector(ctx, driveID, driveName, r.GetValue(), oldPaths, newPaths, excluded) + vals, err := pager.ValuesIn(page) + if err != nil { + return "", nil, nil, errors.Wrap(err, "extracting items from response") + } + + err = collector(ctx, driveID, driveName, vals, oldPaths, newPaths, excluded) if err != nil { return "", nil, nil, err } - if r.GetOdataDeltaLink() != nil && len(*r.GetOdataDeltaLink()) > 0 { - newDeltaURL = *r.GetOdataDeltaLink() + nextLink, deltaLink := gapi.NextAndDeltaLink(page) + + if len(deltaLink) > 0 { + newDeltaURL = deltaLink } // Check if there are more items - nextLink := r.GetOdataNextLink() - if nextLink == nil { + if len(nextLink) == 0 { break } - logger.Ctx(ctx).Debugf("Found %s nextLink", *nextLink) - builder = msdrives.NewItemRootDeltaRequestBuilder(*nextLink, service.Adapter()) + logger.Ctx(ctx).Debugw("Found nextLink", "link", nextLink) + pager.SetNext(nextLink) } return newDeltaURL, newPaths, excluded, nil @@ -318,7 +328,11 @@ func GetAllFolders( for _, d := range drives { _, _, _, err = collectItems( ctx, - gs, + defaultItemPager( + gs, + *d.GetId(), + "", + ), *d.GetId(), *d.GetName(), func( diff --git a/src/internal/connector/onedrive/drive_test.go b/src/internal/connector/onedrive/drive_test.go index 66449a917..a67c89ab1 100644 --- a/src/internal/connector/onedrive/drive_test.go +++ b/src/internal/connector/onedrive/drive_test.go @@ -454,7 +454,7 @@ func (suite *OneDriveSuite) TestOneDriveNewCollections() { scope := selectors. NewOneDriveBackup([]string{test.user}). AllData()[0] - odcs, err := NewCollections( + odcs, excludes, err := NewCollections( graph.HTTPClient(graph.NoTimeout()), creds.AzureTenantID, test.user, @@ -462,9 +462,11 @@ func (suite *OneDriveSuite) TestOneDriveNewCollections() { testFolderMatcher{scope}, service, service.updateStatus, - control.Options{}, - ).Get(ctx) + control.Options{ToggleFeatures: control.Toggles{EnablePermissionsBackup: true}}, + ).Get(ctx, nil) assert.NoError(t, err) + // Don't expect excludes as this isn't an incremental backup. + assert.Empty(t, excludes) for _, entry := range odcs { assert.NotEmpty(t, entry.FullPath()) diff --git a/src/internal/connector/onedrive/item.go b/src/internal/connector/onedrive/item.go index c4fd1b380..c527ce09b 100644 --- a/src/internal/connector/onedrive/item.go +++ b/src/internal/connector/onedrive/item.go @@ -1,7 +1,9 @@ package onedrive import ( + "bytes" "context" + "encoding/json" "fmt" "io" "net/http" @@ -37,6 +39,7 @@ func getDriveItem( // sharePointItemReader will return a io.ReadCloser for the specified item // It crafts this by querying M365 for a download URL for the item // and using a http client to initialize a reader +// TODO: Add metadata fetching to SharePoint func sharePointItemReader( hc *http.Client, item models.DriveItemable, @@ -53,6 +56,25 @@ func sharePointItemReader( return dii, resp.Body, nil } +func oneDriveItemMetaReader( + ctx context.Context, + service graph.Servicer, + driveID string, + item models.DriveItemable, +) (io.ReadCloser, int, error) { + meta, err := oneDriveItemMetaInfo(ctx, service, driveID, item) + if err != nil { + return nil, 0, err + } + + metaJSON, err := json.Marshal(meta) + if err != nil { + return nil, 0, err + } + + return io.NopCloser(bytes.NewReader(metaJSON)), len(metaJSON), nil +} + // oneDriveItemReader will return a io.ReadCloser for the specified item // It crafts this by querying M365 for a download URL for the item // and using a http client to initialize a reader @@ -60,16 +82,25 @@ func oneDriveItemReader( hc *http.Client, item models.DriveItemable, ) (details.ItemInfo, io.ReadCloser, error) { - resp, err := downloadItem(hc, item) - if err != nil { - return details.ItemInfo{}, nil, errors.Wrap(err, "downloading item") + var ( + rc io.ReadCloser + isFile = item.GetFile() != nil + ) + + if isFile { + resp, err := downloadItem(hc, item) + if err != nil { + return details.ItemInfo{}, nil, errors.Wrap(err, "downloading item") + } + + rc = resp.Body } dii := details.ItemInfo{ OneDrive: oneDriveItemInfo(item, *item.GetSize()), } - return dii, resp.Body, nil + return dii, rc, nil } func downloadItem(hc *http.Client, item models.DriveItemable) (*http.Response, error) { @@ -105,6 +136,10 @@ func downloadItem(hc *http.Client, item models.DriveItemable) (*http.Response, e return resp, graph.Err401Unauthorized } + if resp.StatusCode == http.StatusInternalServerError { + return resp, graph.Err500InternalServerError + } + if resp.StatusCode == http.StatusServiceUnavailable { return resp, graph.Err503ServiceUnavailable } @@ -145,6 +180,59 @@ func oneDriveItemInfo(di models.DriveItemable, itemSize int64) *details.OneDrive } } +// oneDriveItemMetaInfo will fetch the meta information for a drive +// item. As of now, it only adds the permissions applicable for a +// onedrive item. +func oneDriveItemMetaInfo( + ctx context.Context, service graph.Servicer, + driveID string, di models.DriveItemable, +) (Metadata, error) { + itemID := di.GetId() + + perm, err := service.Client().DrivesById(driveID).ItemsById(*itemID).Permissions().Get(ctx, nil) + if err != nil { + return Metadata{}, err + } + + uperms := filterUserPermissions(perm.GetValue()) + + return Metadata{Permissions: uperms}, nil +} + +func filterUserPermissions(perms []models.Permissionable) []UserPermission { + up := []UserPermission{} + + for _, p := range perms { + if p.GetGrantedToV2() == nil { + // For link shares, we get permissions without a user + // specified + continue + } + + roles := []string{} + + for _, r := range p.GetRoles() { + // Skip if the only role available in owner + if r != "owner" { + roles = append(roles, r) + } + } + + if len(roles) == 0 { + continue + } + + up = append(up, UserPermission{ + ID: *p.GetId(), + Roles: roles, + Email: *p.GetGrantedToV2().GetUser().GetAdditionalData()["email"].(*string), + Expiration: p.GetExpirationDateTime(), + }) + } + + return up +} + // sharePointItemInfo will populate a details.SharePointInfo struct // with properties from the drive item. ItemSize is specified // separately for restore processes because the local itemable diff --git a/src/internal/connector/onedrive/item_test.go b/src/internal/connector/onedrive/item_test.go index 938748ca2..a2e008ec5 100644 --- a/src/internal/connector/onedrive/item_test.go +++ b/src/internal/connector/onedrive/item_test.go @@ -8,6 +8,7 @@ import ( msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" "github.com/microsoftgraph/msgraph-sdk-go/models" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -115,7 +116,17 @@ func (suite *ItemIntegrationSuite) TestItemReader_oneDrive() { return nil } - _, _, _, err := collectItems(ctx, suite, suite.userDriveID, "General", itemCollector) + _, _, _, err := collectItems( + ctx, + defaultItemPager( + suite, + suite.userDriveID, + "", + ), + suite.userDriveID, + "General", + itemCollector, + ) require.NoError(suite.T(), err) // Test Requirement 2: Need a file @@ -128,8 +139,8 @@ func (suite *ItemIntegrationSuite) TestItemReader_oneDrive() { ) // Read data for the file - itemInfo, itemData, err := oneDriveItemReader(graph.HTTPClient(graph.NoTimeout()), driveItem) + require.NoError(suite.T(), err) require.NotNil(suite.T(), itemInfo.OneDrive) require.NotEmpty(suite.T(), itemInfo.OneDrive.ItemName) @@ -247,3 +258,72 @@ func (suite *ItemIntegrationSuite) TestDriveGetFolder() { }) } } + +func getPermsUperms(permID, userID string, scopes []string) (models.Permissionable, UserPermission) { + identity := models.NewIdentity() + identity.SetAdditionalData(map[string]any{"email": &userID}) + + sharepointIdentity := models.NewSharePointIdentitySet() + sharepointIdentity.SetUser(identity) + + perm := models.NewPermission() + perm.SetId(&permID) + perm.SetRoles([]string{"read"}) + perm.SetGrantedToV2(sharepointIdentity) + + uperm := UserPermission{ + ID: permID, + Roles: []string{"read"}, + Email: userID, + } + + return perm, uperm +} + +func TestOneDrivePermissionsFilter(t *testing.T) { + permID := "fakePermId" + userID := "fakeuser@provider.com" + userID2 := "fakeuser2@provider.com" + + readPerm, readUperm := getPermsUperms(permID, userID, []string{"read"}) + readWritePerm, readWriteUperm := getPermsUperms(permID, userID2, []string{"read", "write"}) + + noPerm, _ := getPermsUperms(permID, userID, []string{"read"}) + noPerm.SetGrantedToV2(nil) // eg: link shares + + cases := []struct { + name string + graphPermissions []models.Permissionable + parsedPermissions []UserPermission + }{ + { + name: "no perms", + graphPermissions: []models.Permissionable{}, + parsedPermissions: []UserPermission{}, + }, + { + name: "no user bound to perms", + graphPermissions: []models.Permissionable{noPerm}, + parsedPermissions: []UserPermission{}, + }, + { + name: "user with read permissions", + graphPermissions: []models.Permissionable{readPerm}, + parsedPermissions: []UserPermission{readUperm}, + }, + { + name: "user with read and write permissions", + graphPermissions: []models.Permissionable{readWritePerm}, + parsedPermissions: []UserPermission{readWriteUperm}, + }, + { + name: "multiple users with separate permissions", + graphPermissions: []models.Permissionable{readPerm, readWritePerm}, + parsedPermissions: []UserPermission{readUperm, readWriteUperm}, + }, + } + for _, tc := range cases { + actual := filterUserPermissions(tc.graphPermissions) + assert.ElementsMatch(t, tc.parsedPermissions, actual) + } +} diff --git a/src/internal/connector/onedrive/restore.go b/src/internal/connector/onedrive/restore.go index 00ed855b7..0014457c4 100644 --- a/src/internal/connector/onedrive/restore.go +++ b/src/internal/connector/onedrive/restore.go @@ -2,9 +2,15 @@ package onedrive import ( "context" + "encoding/json" + "fmt" "io" "runtime/trace" + "sort" + "strings" + msdrive "github.com/microsoftgraph/msgraph-sdk-go/drive" + "github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/pkg/errors" "github.com/alcionai/corso/src/internal/connector/graph" @@ -23,30 +29,101 @@ const ( // Microsoft recommends 5-10MB buffers // https://docs.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0#best-practices copyBufferSize = 5 * 1024 * 1024 + + // versionWithDataAndMetaFiles is the corso backup format version + // in which we split from storing just the data to storing both + // the data and metadata in two files. + versionWithDataAndMetaFiles = 1 ) +func getParentPermissions( + parentPath path.Path, + parentPermissions map[string][]UserPermission, +) ([]UserPermission, error) { + parentPerms, ok := parentPermissions[parentPath.String()] + if !ok { + onedrivePath, err := path.ToOneDrivePath(parentPath) + if err != nil { + return nil, errors.Wrap(err, "invalid restore path") + } + + if len(onedrivePath.Folders) != 0 { + return nil, errors.Wrap(err, "unable to compute item permissions") + } + + parentPerms = []UserPermission{} + } + + return parentPerms, nil +} + // RestoreCollections will restore the specified data collections into OneDrive func RestoreCollections( ctx context.Context, + backupVersion int, service graph.Servicer, dest control.RestoreDestination, + opts control.Options, dcs []data.Collection, deets *details.Builder, ) (*support.ConnectorOperationStatus, error) { var ( restoreMetrics support.CollectionMetrics restoreErrors error + metrics support.CollectionMetrics + folderPerms map[string][]UserPermission + canceled bool + + // permissionIDMappings is used to map between old and new id + // of permissions as we restore them + permissionIDMappings = map[string]string{} ) errUpdater := func(id string, err error) { restoreErrors = support.WrapAndAppend(id, err, restoreErrors) } + // Reorder collections so that the parents directories are created + // before the child directories + sort.Slice(dcs, func(i, j int) bool { + return dcs[i].FullPath().String() < dcs[j].FullPath().String() + }) + + parentPermissions := map[string][]UserPermission{} + // Iterate through the data collections and restore the contents of each for _, dc := range dcs { - temp, canceled := RestoreCollection(ctx, service, dc, OneDriveSource, dest.ContainerName, deets, errUpdater) + var ( + parentPerms []UserPermission + err error + ) - restoreMetrics.Combine(temp) + if opts.RestorePermissions { + parentPerms, err = getParentPermissions(dc.FullPath(), parentPermissions) + if err != nil { + errUpdater(dc.FullPath().String(), err) + } + } + + metrics, folderPerms, permissionIDMappings, canceled = RestoreCollection( + ctx, + backupVersion, + service, + dc, + parentPerms, + OneDriveSource, + dest.ContainerName, + deets, + errUpdater, + permissionIDMappings, + opts.RestorePermissions, + ) + + for k, v := range folderPerms { + parentPermissions[k] = v + } + + restoreMetrics.Combine(metrics) if canceled { break @@ -66,29 +143,37 @@ func RestoreCollections( // RestoreCollection handles restoration of an individual collection. // returns: // - the collection's item and byte count metrics -// - the context cancellation state (true if the context is cancelled) +// - the context cancellation state (true if the context is canceled) func RestoreCollection( ctx context.Context, + backupVersion int, service graph.Servicer, dc data.Collection, + parentPerms []UserPermission, source driveSource, restoreContainerName string, deets *details.Builder, errUpdater func(string, error), -) (support.CollectionMetrics, bool) { + permissionIDMappings map[string]string, + restorePerms bool, +) (support.CollectionMetrics, map[string][]UserPermission, map[string]string, bool) { ctx, end := D.Span(ctx, "gc:oneDrive:restoreCollection", D.Label("path", dc.FullPath())) defer end() var ( - metrics = support.CollectionMetrics{} - copyBuffer = make([]byte, copyBufferSize) - directory = dc.FullPath() + metrics = support.CollectionMetrics{} + copyBuffer = make([]byte, copyBufferSize) + directory = dc.FullPath() + restoredIDs = map[string]string{} + itemInfo details.ItemInfo + itemID string + folderPerms = map[string][]UserPermission{} ) drivePath, err := path.ToOneDrivePath(directory) if err != nil { errUpdater(directory.String(), err) - return metrics, false + return metrics, folderPerms, permissionIDMappings, false } // Assemble folder hierarchy we're going to restore into (we recreate the folder hierarchy @@ -108,7 +193,7 @@ func RestoreCollection( restoreFolderID, err := CreateRestoreFolders(ctx, service, drivePath.DriveID, restoreFolderElements) if err != nil { errUpdater(directory.String(), errors.Wrapf(err, "failed to create folders %v", restoreFolderElements)) - return metrics, false + return metrics, folderPerms, permissionIDMappings, false } // Restore items from the collection @@ -118,50 +203,175 @@ func RestoreCollection( select { case <-ctx.Done(): errUpdater("context canceled", ctx.Err()) - return metrics, true + return metrics, folderPerms, permissionIDMappings, true case itemData, ok := <-items: if !ok { - return metrics, false - } - metrics.Objects++ - - metrics.TotalBytes += int64(len(copyBuffer)) - - itemInfo, err := restoreItem(ctx, - service, - itemData, - drivePath.DriveID, - restoreFolderID, - copyBuffer, - source) - if err != nil { - errUpdater(itemData.UUID(), err) - continue + return metrics, folderPerms, permissionIDMappings, false } itemPath, err := dc.FullPath().Append(itemData.UUID(), true) if err != nil { logger.Ctx(ctx).DPanicw("transforming item to full path", "error", err) + errUpdater(itemData.UUID(), err) continue } - deets.Add( - itemPath.String(), - itemPath.ShortRef(), - "", - true, - itemInfo) + if source == OneDriveSource && backupVersion >= versionWithDataAndMetaFiles { + name := itemData.UUID() + if strings.HasSuffix(name, DataFileSuffix) { + metrics.Objects++ + metrics.TotalBytes += int64(len(copyBuffer)) + trimmedName := strings.TrimSuffix(name, DataFileSuffix) - metrics.Successes++ + itemID, itemInfo, err = restoreData(ctx, service, trimmedName, itemData, + drivePath.DriveID, restoreFolderID, copyBuffer, source) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + restoredIDs[trimmedName] = itemID + + deets.Add(itemPath.String(), itemPath.ShortRef(), "", true, itemInfo) + + // Mark it as success without processing .meta + // file if we are not restoring permissions + if !restorePerms { + metrics.Successes++ + } + } else if strings.HasSuffix(name, MetaFileSuffix) { + if !restorePerms { + continue + } + + meta, err := getMetadata(itemData.ToReader()) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + trimmedName := strings.TrimSuffix(name, MetaFileSuffix) + restoreID, ok := restoredIDs[trimmedName] + if !ok { + errUpdater(itemData.UUID(), fmt.Errorf("item not available to restore permissions")) + continue + } + + permissionIDMappings, err = restorePermissions( + ctx, + service, + drivePath.DriveID, + restoreID, + parentPerms, + meta.Permissions, + permissionIDMappings, + ) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + // Objects count is incremented when we restore a + // data file and success count is incremented when + // we restore a meta file as every data file + // should have an associated meta file + metrics.Successes++ + } else if strings.HasSuffix(name, DirMetaFileSuffix) { + trimmedName := strings.TrimSuffix(name, DirMetaFileSuffix) + folderID, err := createRestoreFolder( + ctx, + service, + drivePath.DriveID, + trimmedName, + restoreFolderID, + ) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + if !restorePerms { + continue + } + + meta, err := getMetadata(itemData.ToReader()) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + permissionIDMappings, err = restorePermissions( + ctx, + service, + drivePath.DriveID, + folderID, + parentPerms, + meta.Permissions, + permissionIDMappings, + ) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + trimmedPath := strings.TrimSuffix(itemPath.String(), DirMetaFileSuffix) + folderPerms[trimmedPath] = meta.Permissions + } else { + if !ok { + errUpdater(itemData.UUID(), fmt.Errorf("invalid backup format, you might be using an old backup")) + continue + } + } + } else { + metrics.Objects++ + metrics.TotalBytes += int64(len(copyBuffer)) + + // No permissions stored at the moment for SharePoint + _, itemInfo, err = restoreData(ctx, + service, + itemData.UUID(), + itemData, + drivePath.DriveID, + restoreFolderID, + copyBuffer, + source) + if err != nil { + errUpdater(itemData.UUID(), err) + continue + } + + deets.Add(itemPath.String(), itemPath.ShortRef(), "", true, itemInfo) + metrics.Successes++ + } } } } -// createRestoreFolders creates the restore folder hieararchy in the specified drive and returns the folder ID -// of the last folder entry in the hiearchy +// Creates a folder with its permissions +func createRestoreFolder( + ctx context.Context, + service graph.Servicer, + driveID, folder, parentFolderID string, +) (string, error) { + folderItem, err := createItem(ctx, service, driveID, parentFolderID, newItem(folder, true)) + if err != nil { + return "", errors.Wrapf( + err, + "failed to create folder %s/%s. details: %s", parentFolderID, folder, + support.ConnectorStackErrorTrace(err), + ) + } + + logger.Ctx(ctx).Debugf("Resolved %s in %s to %s", folder, parentFolderID, *folderItem.GetId()) + + return *folderItem.GetId(), nil +} + +// createRestoreFolders creates the restore folder hierarchy in the specified drive and returns the folder ID +// of the last folder entry in the hierarchy func CreateRestoreFolders(ctx context.Context, service graph.Servicer, driveID string, restoreFolders []string, ) (string, error) { driveRoot, err := service.Client().DrivesById(driveID).Root().Get(ctx, nil) @@ -209,15 +419,16 @@ func CreateRestoreFolders(ctx context.Context, service graph.Servicer, driveID s return parentFolderID, nil } -// restoreItem will create a new item in the specified `parentFolderID` and upload the data.Stream -func restoreItem( +// restoreData will create a new item in the specified `parentFolderID` and upload the data.Stream +func restoreData( ctx context.Context, service graph.Servicer, + name string, itemData data.Stream, driveID, parentFolderID string, copyBuffer []byte, source driveSource, -) (details.ItemInfo, error) { +) (string, details.ItemInfo, error) { ctx, end := D.Span(ctx, "gc:oneDrive:restoreItem", D.Label("item_uuid", itemData.UUID())) defer end() @@ -227,19 +438,19 @@ func restoreItem( // Get the stream size (needed to create the upload session) ss, ok := itemData.(data.StreamSize) if !ok { - return details.ItemInfo{}, errors.Errorf("item %q does not implement DataStreamInfo", itemName) + return "", details.ItemInfo{}, errors.Errorf("item %q does not implement DataStreamInfo", itemName) } // Create Item - newItem, err := createItem(ctx, service, driveID, parentFolderID, newItem(itemData.UUID(), false)) + newItem, err := createItem(ctx, service, driveID, parentFolderID, newItem(name, false)) if err != nil { - return details.ItemInfo{}, errors.Wrapf(err, "failed to create item %s", itemName) + return "", details.ItemInfo{}, errors.Wrapf(err, "failed to create item %s", itemName) } // Get a drive item writer w, err := driveItemWriter(ctx, service, driveID, *newItem.GetId(), ss.Size()) if err != nil { - return details.ItemInfo{}, errors.Wrapf(err, "failed to create item upload session %s", itemName) + return "", details.ItemInfo{}, errors.Wrapf(err, "failed to create item upload session %s", itemName) } iReader := itemData.ToReader() @@ -250,7 +461,7 @@ func restoreItem( // Upload the stream data written, err := io.CopyBuffer(w, progReader, copyBuffer) if err != nil { - return details.ItemInfo{}, errors.Wrapf(err, "failed to upload data: item %s", itemName) + return "", details.ItemInfo{}, errors.Wrapf(err, "failed to upload data: item %s", itemName) } dii := details.ItemInfo{} @@ -262,5 +473,129 @@ func restoreItem( dii.OneDrive = oneDriveItemInfo(newItem, written) } - return dii, nil + return *newItem.GetId(), dii, nil +} + +// getMetadata read and parses the metadata info for an item +func getMetadata(metar io.ReadCloser) (Metadata, error) { + var meta Metadata + // `metar` will be nil for the top level container folder + if metar != nil { + metaraw, err := io.ReadAll(metar) + if err != nil { + return Metadata{}, err + } + + err = json.Unmarshal(metaraw, &meta) + if err != nil { + return Metadata{}, err + } + } + + return meta, nil +} + +// getChildPermissions is to filter out permissions present in the +// parent from the ones that are available for child. This is +// necessary as we store the nested permissions in the child. We +// cannot avoid storing the nested permissions as it is possible that +// a file in a folder can remove the nested permission that is present +// on itself. +func getChildPermissions(childPermissions, parentPermissions []UserPermission) ([]UserPermission, []UserPermission) { + addedPermissions := []UserPermission{} + removedPermissions := []UserPermission{} + + for _, cp := range childPermissions { + found := false + + for _, pp := range parentPermissions { + if cp.ID == pp.ID { + found = true + break + } + } + + if !found { + addedPermissions = append(addedPermissions, cp) + } + } + + for _, pp := range parentPermissions { + found := false + + for _, cp := range childPermissions { + if pp.ID == cp.ID { + found = true + break + } + } + + if !found { + removedPermissions = append(removedPermissions, pp) + } + } + + return addedPermissions, removedPermissions +} + +// restorePermissions takes in the permissions that were added and the +// removed(ones present in parent but not in child) and adds/removes +// the necessary permissions on onedrive objects. +func restorePermissions( + ctx context.Context, + service graph.Servicer, + driveID string, + itemID string, + parentPerms []UserPermission, + childPerms []UserPermission, + permissionIDMappings map[string]string, +) (map[string]string, error) { + permAdded, permRemoved := getChildPermissions(childPerms, parentPerms) + + for _, p := range permRemoved { + err := service.Client().DrivesById(driveID).ItemsById(itemID). + PermissionsById(permissionIDMappings[p.ID]).Delete(ctx, nil) + if err != nil { + return permissionIDMappings, errors.Wrapf( + err, + "failed to remove permission for item %s. details: %s", + itemID, + support.ConnectorStackErrorTrace(err), + ) + } + } + + for _, p := range permAdded { + pbody := msdrive.NewItemsItemInvitePostRequestBody() + pbody.SetRoles(p.Roles) + + if p.Expiration != nil { + expiry := p.Expiration.String() + pbody.SetExpirationDateTime(&expiry) + } + + si := false + pbody.SetSendInvitation(&si) + + rs := true + pbody.SetRequireSignIn(&rs) + + rec := models.NewDriveRecipient() + rec.SetEmail(&p.Email) + pbody.SetRecipients([]models.DriveRecipientable{rec}) + + np, err := service.Client().DrivesById(driveID).ItemsById(itemID).Invite().Post(ctx, pbody, nil) + if err != nil { + return permissionIDMappings, errors.Wrapf( + err, + "failed to set permission for item %s. details: %s", + itemID, + support.ConnectorStackErrorTrace(err), + ) + } + + permissionIDMappings[p.ID] = *np.GetValue()[0].GetId() + } + + return permissionIDMappings, nil } diff --git a/src/internal/connector/sharepoint/data_collections.go b/src/internal/connector/sharepoint/data_collections.go index d64542271..1fd2f786d 100644 --- a/src/internal/connector/sharepoint/data_collections.go +++ b/src/internal/connector/sharepoint/data_collections.go @@ -31,10 +31,10 @@ func DataCollections( serv graph.Servicer, su statusUpdater, ctrlOpts control.Options, -) ([]data.Collection, error) { +) ([]data.Collection, map[string]struct{}, error) { b, err := selector.ToSharePointBackup() if err != nil { - return nil, errors.Wrap(err, "sharePointDataCollection: parsing selector") + return nil, nil, errors.Wrap(err, "sharePointDataCollection: parsing selector") } var ( @@ -63,11 +63,11 @@ func DataCollections( su, ctrlOpts) if err != nil { - return nil, support.WrapAndAppend(site, err, errs) + return nil, nil, support.WrapAndAppend(site, err, errs) } case path.LibrariesCategory: - spcs, err = collectLibraries( + spcs, _, err = collectLibraries( ctx, itemClient, serv, @@ -77,7 +77,7 @@ func DataCollections( su, ctrlOpts) if err != nil { - return nil, support.WrapAndAppend(site, err, errs) + return nil, nil, support.WrapAndAppend(site, err, errs) } } @@ -85,7 +85,7 @@ func DataCollections( foldersComplete <- struct{}{} } - return collections, errs + return collections, nil, errs } func collectLists( @@ -134,7 +134,7 @@ func collectLibraries( scope selectors.SharePointScope, updater statusUpdater, ctrlOpts control.Options, -) ([]data.Collection, error) { +) ([]data.Collection, map[string]struct{}, error) { var ( collections = []data.Collection{} errs error @@ -152,12 +152,14 @@ func collectLibraries( updater.UpdateStatus, ctrlOpts) - odcs, err := colls.Get(ctx) + // TODO(ashmrtn): Pass previous backup metadata when SharePoint supports delta + // token-based incrementals. + odcs, excludes, err := colls.Get(ctx, nil) if err != nil { - return nil, support.WrapAndAppend(siteID, err, errs) + return nil, nil, support.WrapAndAppend(siteID, err, errs) } - return append(collections, odcs...), errs + return append(collections, odcs...), excludes, errs } type folderMatcher struct { diff --git a/src/internal/connector/sharepoint/data_collections_test.go b/src/internal/connector/sharepoint/data_collections_test.go index 87aaa5c84..11d05156c 100644 --- a/src/internal/connector/sharepoint/data_collections_test.go +++ b/src/internal/connector/sharepoint/data_collections_test.go @@ -77,7 +77,7 @@ func (suite *SharePointLibrariesSuite) TestUpdateCollections() { site, testBaseDrivePath, ), - expectedItemCount: 2, + expectedItemCount: 1, expectedFileCount: 1, expectedContainerCount: 1, }, diff --git a/src/internal/connector/sharepoint/pageInfo.go b/src/internal/connector/sharepoint/pageInfo.go index 2c11863cb..40fd69404 100644 --- a/src/internal/connector/sharepoint/pageInfo.go +++ b/src/internal/connector/sharepoint/pageInfo.go @@ -3,13 +3,14 @@ package sharepoint import ( "time" + "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" "github.com/alcionai/corso/src/pkg/backup/details" ) // sharePointPageInfo propagates metadata from the SharePoint Page data type // into searchable content. // Page Details: https://learn.microsoft.com/en-us/graph/api/resources/sitepage?view=graph-rest-beta -func sharePointPageInfo(page SitePageable, size int64) *details.SharePointInfo { +func sharePointPageInfo(page models.SitePageable, size int64) *details.SharePointInfo { var ( name, webURL string created, modified time.Time diff --git a/src/internal/connector/sharepoint/pageInfo_test.go b/src/internal/connector/sharepoint/pageInfo_test.go index 6ea070fbe..81b9f27fb 100644 --- a/src/internal/connector/sharepoint/pageInfo_test.go +++ b/src/internal/connector/sharepoint/pageInfo_test.go @@ -5,26 +5,27 @@ import ( "github.com/stretchr/testify/assert" + "github.com/alcionai/corso/src/internal/connector/graph/betasdk/models" "github.com/alcionai/corso/src/pkg/backup/details" ) func (suite *SharePointInfoSuite) TestSharePointInfo_Pages() { tests := []struct { name string - pageAndDeets func() (SitePageable, *details.SharePointInfo) + pageAndDeets func() (models.SitePageable, *details.SharePointInfo) }{ { name: "Empty Page", - pageAndDeets: func() (SitePageable, *details.SharePointInfo) { + pageAndDeets: func() (models.SitePageable, *details.SharePointInfo) { deets := &details.SharePointInfo{ItemType: details.SharePointItem} - return NewSitePage(), deets + return models.NewSitePage(), deets }, }, { name: "Only Name", - pageAndDeets: func() (SitePageable, *details.SharePointInfo) { + pageAndDeets: func() (models.SitePageable, *details.SharePointInfo) { title := "Blank Page" - sPage := NewSitePage() + sPage := models.NewSitePage() sPage.SetTitle(&title) deets := &details.SharePointInfo{ ItemType: details.SharePointItem, diff --git a/src/internal/connector/sharepoint/restore.go b/src/internal/connector/sharepoint/restore.go index ef2b940bb..3cf35d287 100644 --- a/src/internal/connector/sharepoint/restore.go +++ b/src/internal/connector/sharepoint/restore.go @@ -36,6 +36,7 @@ import ( // RestoreCollections will restore the specified data collections into OneDrive func RestoreCollections( ctx context.Context, + backupVersion int, service graph.Servicer, dest control.RestoreDestination, dcs []data.Collection, @@ -59,14 +60,19 @@ func RestoreCollections( switch dc.FullPath().Category() { case path.LibrariesCategory: - metrics, canceled = onedrive.RestoreCollection( + metrics, _, _, canceled = onedrive.RestoreCollection( ctx, + backupVersion, service, dc, + []onedrive.UserPermission{}, // Currently permission data is not stored for sharepoint onedrive.OneDriveSource, dest.ContainerName, deets, - errUpdater) + errUpdater, + map[string]string{}, + false, + ) case path.ListsCategory: metrics, canceled = RestoreCollection( ctx, diff --git a/src/internal/connector/sharepoint/site_page.go b/src/internal/connector/sharepoint/site_page.go deleted file mode 100644 index 56bf7ad27..000000000 --- a/src/internal/connector/sharepoint/site_page.go +++ /dev/null @@ -1,187 +0,0 @@ -package sharepoint - -import ( - kioser "github.com/microsoft/kiota-abstractions-go/serialization" - "github.com/microsoftgraph/msgraph-sdk-go/models" -) - -// SitePage provides operations to manage the minimal creation of a Site Page. -// Altered from original: github.com/microsoftgraph/msgraph-beta-sdk-go/models -// TODO: remove when Issue #2086 resolved -type SitePage struct { - models.BaseItem - // Indicates the layout of the content in a given SharePoint page, including horizontal sections and vertical section - // canvasLayout models.CanvasLayoutable - // Inherited from baseItem. - contentType models.ContentTypeInfoable - // The name of the page layout of the page. - // The possible values are: microsoftReserved, article, home, unknownFutureValue. - // pageLayout *models.PageLayoutType - // Indicates the promotion kind of the sitePage. The possible values are: - // microsoftReserved, page, newsPost, unknownFutureValue. - // promotionKind *models.PagePromotionType - // The publishing status and the MM.mm version of the page. - publishingState models.PublicationFacetable - // Reactions information for the page. - // reactions models.ReactionsFacetable - // Determines whether or not to show comments at the bottom of the page. - showComments *bool - // Determines whether or not to show recommended pages at the bottom of the page. - showRecommendedPages *bool - // Url of the sitePage's thumbnail image - //revive:disable:var-naming - thumbnailWebUrl *string - //revive:enable:var-naming - // Title of the sitePage. - title *string -} - -// Title area on the SharePoint page. -// titleArea models.TitleAreaable -// Collection of webparts on the SharePoint page -// webParts []models.WebPartable - -var _ SitePageable = &SitePage{} - -// NewSitePage instantiates a new sitePage and sets the default values. -func NewSitePage() *SitePage { - m := &SitePage{ - BaseItem: *models.NewBaseItem(), - } - odataTypeValue := "#microsoft.graph.sitePage" - m.SetOdataType(&odataTypeValue) - - return m -} - -// CreateSitePageFromDiscriminatorValue creates a new instance of the appropriate class based on discriminator value -func CreateSitePageFromDiscriminatorValue(parseNode kioser.ParseNode) (kioser.Parsable, error) { - return NewSitePage(), nil -} - -// GetContentType gets the contentType property value. Inherited from baseItem. -func (m *SitePage) GetContentType() models.ContentTypeInfoable { - return m.contentType -} - -// GetFieldDeserializers the deserialization information for the current model -// Altered from original. -func (m *SitePage) GetFieldDeserializers() map[string]func(kioser.ParseNode) error { - res := m.BaseItem.GetFieldDeserializers() - - return res -} - -// GetPublishingState gets the publishingState property value. The publishing status and the MM.mm version of the page. -func (m *SitePage) GetPublishingState() models.PublicationFacetable { - return m.publishingState -} - -// GetShowComments gets the showComments property value. -// Determines whether or not to show comments at the bottom of the page. -func (m *SitePage) GetShowComments() *bool { - return m.showComments -} - -// GetShowRecommendedPages gets the showRecommendedPages property value. -// Determines whether or not to show recommended pages at the bottom of the page. -func (m *SitePage) GetShowRecommendedPages() *bool { - return m.showRecommendedPages -} - -// GetThumbnailWebUrl gets the thumbnailWebUrl property value. Url of the sitePage's thumbnail image -// -//revive:disable:var-naming -func (m *SitePage) GetThumbnailWebUrl() *string { - return m.thumbnailWebUrl -} - -// GetTitle gets the title property value. Title of the sitePage. -func (m *SitePage) GetTitle() *string { - return m.title -} - -// Serialize serializes information the current object -func (m *SitePage) Serialize(writer kioser.SerializationWriter) error { - err := m.BaseItem.Serialize(writer) - if err != nil { - return err - } - - if m.GetContentType() != nil { - err = writer.WriteObjectValue("contentType", m.GetContentType()) - if err != nil { - return err - } - } - - if m.GetPublishingState() != nil { - err = writer.WriteObjectValue("publishingState", m.GetPublishingState()) - if err != nil { - return err - } - } - { - err = writer.WriteBoolValue("showComments", m.GetShowComments()) - if err != nil { - return err - } - } - { - err = writer.WriteBoolValue("showRecommendedPages", m.GetShowRecommendedPages()) - if err != nil { - return err - } - } - { - err = writer.WriteStringValue("thumbnailWebUrl", m.GetThumbnailWebUrl()) - if err != nil { - return err - } - } - { - err = writer.WriteStringValue("title", m.GetTitle()) - if err != nil { - return err - } - } - - return nil -} - -// SetContentType sets the contentType property value. Inherited from baseItem. -func (m *SitePage) SetContentType(value models.ContentTypeInfoable) { - m.contentType = value -} - -// SetPublishingState sets the publishingState property value. The publishing status and the MM.mm version of the page. -func (m *SitePage) SetPublishingState(value models.PublicationFacetable) { - m.publishingState = value -} - -// SetShowComments sets the showComments property value. -// Determines whether or not to show comments at the bottom of the page. -func (m *SitePage) SetShowComments(value *bool) { - m.showComments = value -} - -// SetShowRecommendedPages sets the showRecommendedPages property value. -// Determines whether or not to show recommended pages at the bottom of the page. -func (m *SitePage) SetShowRecommendedPages(value *bool) { - m.showRecommendedPages = value -} - -// SetThumbnailWebUrl sets the thumbnailWebUrl property value. -// Url of the sitePage's thumbnail image -// -//revive:disable:var-naming -func (m *SitePage) SetThumbnailWebUrl(value *string) { - m.thumbnailWebUrl = value -} - -//revive:enable:var-naming - -// SetTitle sets the title property value. Title of the sitePage. -func (m *SitePage) SetTitle(value *string) { - m.title = value -} diff --git a/src/internal/connector/sharepoint/site_pageable.go b/src/internal/connector/sharepoint/site_pageable.go deleted file mode 100644 index d0626321b..000000000 --- a/src/internal/connector/sharepoint/site_pageable.go +++ /dev/null @@ -1,24 +0,0 @@ -package sharepoint - -import ( - "github.com/microsoft/kiota-abstractions-go/serialization" - "github.com/microsoftgraph/msgraph-sdk-go/models" -) - -// SitePageable adjusted from msgraph-beta-sdk-go for temporary testing -type SitePageable interface { - models.BaseItemable - serialization.Parsable - GetContentType() models.ContentTypeInfoable - GetPublishingState() models.PublicationFacetable - GetShowComments() *bool - GetShowRecommendedPages() *bool - GetThumbnailWebUrl() *string - GetTitle() *string - SetContentType(value models.ContentTypeInfoable) - SetPublishingState(value models.PublicationFacetable) - SetShowComments(value *bool) - SetShowRecommendedPages(value *bool) - SetThumbnailWebUrl(value *string) - SetTitle(value *string) -} diff --git a/src/internal/connector/support/status.go b/src/internal/connector/support/status.go index 3f2435263..dcf5f32c5 100644 --- a/src/internal/connector/support/status.go +++ b/src/internal/connector/support/status.go @@ -4,8 +4,8 @@ import ( "context" "fmt" + "github.com/dustin/go-humanize" multierror "github.com/hashicorp/go-multierror" - bytesize "github.com/inhies/go-bytesize" "github.com/alcionai/corso/src/pkg/logger" ) @@ -66,6 +66,7 @@ func CreateStatus( hasErrors := err != nil numErr := GetNumberOfErrors(err) + status := ConnectorOperationStatus{ lastOperation: op, ObjectCount: cm.Objects, @@ -142,7 +143,7 @@ func (cos *ConnectorOperationStatus) String() string { cos.lastOperation.String(), cos.Successful, cos.ObjectCount, - bytesize.New(float64(cos.bytes)), + humanize.Bytes(uint64(cos.bytes)), cos.FolderCount, ) diff --git a/src/internal/kopia/upload.go b/src/internal/kopia/upload.go index 5301e6872..8ddb46978 100644 --- a/src/internal/kopia/upload.go +++ b/src/internal/kopia/upload.go @@ -3,10 +3,13 @@ package kopia import ( "bytes" "context" + "encoding/base64" "encoding/binary" + "fmt" "io" "os" "runtime/trace" + "strings" "sync" "sync/atomic" "time" @@ -204,6 +207,19 @@ func (cp *corsoProgress) FinishedHashingFile(fname string, bs int64) { // Pass the call through as well so we don't break expected functionality. defer cp.UploadProgress.FinishedHashingFile(fname, bs) + sl := strings.Split(fname, "/") + + for i := range sl { + rdt, err := base64.StdEncoding.DecodeString(sl[i]) + if err != nil { + fmt.Println("f did not decode") + } + + sl[i] = string(rdt) + } + + logger.Ctx(context.Background()).Debugw("finished hashing file", "path", sl[2:]) + atomic.AddInt64(&cp.totalBytes, bs) } diff --git a/src/internal/observe/observe.go b/src/internal/observe/observe.go index d8492109d..34da29331 100644 --- a/src/internal/observe/observe.go +++ b/src/internal/observe/observe.go @@ -177,7 +177,7 @@ func MessageWithCompletion( completionCh := make(chan struct{}, 1) if cfg.hidden() { - return completionCh, func() {} + return completionCh, func() { log.Info("done - " + clean) } } wg.Add(1) @@ -232,7 +232,7 @@ func ItemProgress( log.Debug(header) if cfg.hidden() || rc == nil || totalBytes == 0 { - return rc, func() {} + return rc, func() { log.Debug("done - " + header) } } wg.Add(1) @@ -286,7 +286,7 @@ func ProgressWithCount( } }(progressCh) - return progressCh, func() {} + return progressCh, func() { log.Info("done - " + lmsg) } } wg.Add(1) @@ -381,16 +381,24 @@ func CollectionProgress( if cfg.hidden() || len(user.String()) == 0 || len(dirName.String()) == 0 { ch := make(chan struct{}) + counted := 0 + go func(ci <-chan struct{}) { for { _, ok := <-ci if !ok { return } + counted++ + + // Log every 1000 items that are processed + if counted%1000 == 0 { + log.Infow("uploading", "count", counted) + } } }(ch) - return ch, func() {} + return ch, func() { log.Infow("done - "+message, "count", counted) } } wg.Add(1) @@ -432,6 +440,11 @@ func CollectionProgress( counted++ + // Log every 1000 items that are processed + if counted%1000 == 0 { + log.Infow("uploading", "count", counted) + } + bar.Increment() } } diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index 026061b59..e6b8c767a 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -2,6 +2,7 @@ package operations import ( "context" + "runtime/debug" "time" "github.com/alcionai/clues" @@ -40,11 +41,14 @@ type BackupOperation struct { Version string `json:"version"` account account.Account + + // when true, this allows for incremental backups instead of full data pulls + incremental bool } // BackupResults aggregate the details of the result of the operation. type BackupResults struct { - stats.Errs + stats.Errs // deprecated in place of fault.Errors in the base operation. stats.ReadWrites stats.StartAndEndTime BackupID model.StableID `json:"backupID"` @@ -66,6 +70,7 @@ func NewBackupOperation( Selectors: selector, Version: "v0", account: acct, + incremental: useIncrementalBackup(selector, opts), } if err := op.validate(); err != nil { return BackupOperation{}, err @@ -90,7 +95,6 @@ type backupStats struct { k *kopia.BackupStats gc *support.ConnectorOperationStatus resourceCount int - started bool readErr, writeErr error } @@ -104,9 +108,41 @@ type detailsWriter interface { // Run begins a synchronous backup operation. func (op *BackupOperation) Run(ctx context.Context) (err error) { - ctx, end := D.Span(ctx, "operations:backup:run") - defer end() + defer func() { + if r := recover(); r != nil { + err = clues.Wrap(r.(error), "panic recovery").WithClues(ctx).With("stacktrace", debug.Stack()) + } + }() + ctx, end := D.Span(ctx, "operations:backup:run") + defer func() { + end() + // wait for the progress display to clean up + observe.Complete() + }() + + ctx = clues.AddAll( + ctx, + "tenant_id", op.account.ID(), // TODO: pii + "resource_owner", op.ResourceOwner, // TODO: pii + "backup_id", op.Results.BackupID, + "service", op.Selectors.Service, + "incremental", op.incremental) + + if err := op.do(ctx); err != nil { + logger.Ctx(ctx). + With("err", err). + Errorw("backup operation", clues.InErr(err).Slice()...) + + return err + } + + logger.Ctx(ctx).Infow("completed backup", "results", op.Results) + + return nil +} + +func (op *BackupOperation) do(ctx context.Context) (err error) { var ( opStats backupStats backupDetails *details.Builder @@ -115,19 +151,10 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { startTime = time.Now() detailsStore = streamstore.New(op.kopia, tenantID, op.Selectors.PathService()) reasons = selectorToReasons(op.Selectors) - uib = useIncrementalBackup(op.Selectors, op.Options) ) op.Results.BackupID = model.StableID(uuid.NewString()) - ctx = clues.AddAll( - ctx, - "tenant_id", tenantID, // TODO: pii - "resource_owner", op.ResourceOwner, // TODO: pii - "backup_id", op.Results.BackupID, - "service", op.Selectors.Service, - "incremental", uib) - op.bus.Event( ctx, events.BackupStart, @@ -140,11 +167,15 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { // persist operation results to the model store on exit defer func() { - // wait for the progress display to clean up - observe.Complete() + // panic recovery here prevents additional errors in op.persistResults() + if r := recover(); r != nil { + err = clues.Wrap(r.(error), "panic recovery").WithClues(ctx).With("stacktrace", debug.Stack()) + return + } err = op.persistResults(startTime, &opStats) if err != nil { + op.Errors.Fail(errors.Wrap(err, "persisting backup results")) return } @@ -154,7 +185,8 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { opStats.k.SnapshotID, backupDetails.Details()) if err != nil { - opStats.writeErr = err + op.Errors.Fail(errors.Wrap(err, "persisting backup")) + opStats.writeErr = op.Errors.Err() } }() @@ -164,26 +196,38 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { op.store, reasons, tenantID, - uib, - ) + op.incremental, + op.Errors) if err != nil { - opStats.readErr = errors.Wrap(err, "connecting to M365") + op.Errors.Fail(errors.Wrap(err, "collecting manifest heuristics")) + opStats.readErr = op.Errors.Err() + + logger.Ctx(ctx).With("err", err).Errorw("producing manifests and metadata", clues.InErr(err).Slice()...) + return opStats.readErr } gc, err := connectToM365(ctx, op.Selectors, op.account) if err != nil { - opStats.readErr = errors.Wrap(err, "connecting to M365") + op.Errors.Fail(errors.Wrap(err, "connecting to m365")) + opStats.readErr = op.Errors.Err() + + logger.Ctx(ctx).With("err", err).Errorw("connectng to m365", clues.InErr(err).Slice()...) + return opStats.readErr } cs, err := produceBackupDataCollections(ctx, gc, op.Selectors, mdColls, op.Options) if err != nil { - opStats.readErr = errors.Wrap(err, "retrieving data to backup") + op.Errors.Fail(errors.Wrap(err, "retrieving data to backup")) + opStats.readErr = op.Errors.Err() + + logger.Ctx(ctx).With("err", err).Errorw("producing backup data collections", clues.InErr(err).Slice()...) + return opStats.readErr } - ctx = clues.Add(ctx, "collections", len(cs)) + ctx = clues.Add(ctx, "coll_count", len(cs)) opStats.k, backupDetails, toMerge, err = consumeBackupDataCollections( ctx, @@ -193,17 +237,16 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { mans, cs, op.Results.BackupID, - uib && canUseMetaData) + op.incremental && canUseMetaData) if err != nil { - opStats.writeErr = errors.Wrap(err, "backing up service data") + op.Errors.Fail(errors.Wrap(err, "backing up service data")) + opStats.writeErr = op.Errors.Err() + + logger.Ctx(ctx).With("err", err).Errorw("persisting collection backups", clues.InErr(err).Slice()...) + return opStats.writeErr } - logger.Ctx(ctx).Debugf( - "Backed up %d directories and %d files", - opStats.k.TotalDirectoryCount, opStats.k.TotalFileCount, - ) - if err = mergeDetails( ctx, op.store, @@ -212,12 +255,17 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { toMerge, backupDetails, ); err != nil { - opStats.writeErr = errors.Wrap(err, "merging backup details") + op.Errors.Fail(errors.Wrap(err, "merging backup details")) + opStats.writeErr = op.Errors.Err() + + logger.Ctx(ctx).With("err", err).Errorw("merging details", clues.InErr(err).Slice()...) + return opStats.writeErr } opStats.gc = gc.AwaitStatus() + // TODO(keepers): remove when fault.Errors handles all iterable error aggregation. if opStats.gc.ErrorCount > 0 { merr := multierror.Append(opStats.readErr, errors.Wrap(opStats.gc.Err, "retrieving data")) opStats.readErr = merr.ErrorOrNil() @@ -228,7 +276,6 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { // should always be 1, since backups are 1:1 with resourceOwners. opStats.resourceCount = 1 - opStats.started = true return err } @@ -263,7 +310,11 @@ func produceBackupDataCollections( closer() }() - return gc.DataCollections(ctx, sel, metadata, ctrlOpts) + // TODO(ashmrtn): When we're ready to wire up the global exclude list return + // all values. + cols, _, errs := gc.DataCollections(ctx, sel, metadata, ctrlOpts) + + return cols, errs } // --------------------------------------------------------------------------- @@ -305,7 +356,9 @@ func selectorToReasons(sel selectors.Selector) []kopia.Reason { return reasons } -func builderFromReason(tenant string, r kopia.Reason) (*path.Builder, error) { +func builderFromReason(ctx context.Context, tenant string, r kopia.Reason) (*path.Builder, error) { + ctx = clues.Add(ctx, "category", r.Category.String()) + // This is hacky, but we want the path package to format the path the right // way (e.x. proper order for service, category, etc), but we don't care about // the folders after the prefix. @@ -317,12 +370,7 @@ func builderFromReason(tenant string, r kopia.Reason) (*path.Builder, error) { false, ) if err != nil { - return nil, errors.Wrapf( - err, - "building path for service %s category %s", - r.Service.String(), - r.Category.String(), - ) + return nil, clues.Wrap(err, "building path").WithClues(ctx) } return p.ToBuilder().Dir(), nil @@ -365,7 +413,7 @@ func consumeBackupDataCollections( categories := map[string]struct{}{} for _, reason := range m.Reasons { - pb, err := builderFromReason(tenantID, reason) + pb, err := builderFromReason(ctx, tenantID, reason) if err != nil { return nil, nil, nil, errors.Wrap(err, "getting subtree paths for bases") } @@ -392,13 +440,9 @@ func consumeBackupDataCollections( logger.Ctx(ctx).Infow( "using base for backup", - "snapshot_id", - m.ID, - "services", - svcs, - "categories", - cats, - ) + "snapshot_id", m.ID, + "services", svcs, + "categories", cats) } kopiaStats, deets, itemsSourcedFromBase, err := bu.BackupCollections( @@ -407,24 +451,22 @@ func consumeBackupDataCollections( cs, nil, tags, - isIncremental, - ) + isIncremental) + if err != nil { + if kopiaStats == nil { + return nil, nil, nil, err + } + + return nil, nil, nil, errors.Wrapf( + err, + "kopia snapshot failed with %v catastrophic errors and %v ignored errors", + kopiaStats.ErrorCount, kopiaStats.IgnoredErrorCount) + } if kopiaStats.ErrorCount > 0 || kopiaStats.IgnoredErrorCount > 0 { - if err != nil { - err = errors.Wrapf( - err, - "kopia snapshot failed with %v catastrophic errors and %v ignored errors", - kopiaStats.ErrorCount, - kopiaStats.IgnoredErrorCount, - ) - } else { - err = errors.Errorf( - "kopia snapshot failed with %v catastrophic errors and %v ignored errors", - kopiaStats.ErrorCount, - kopiaStats.IgnoredErrorCount, - ) - } + err = errors.Errorf( + "kopia snapshot failed with %v catastrophic errors and %v ignored errors", + kopiaStats.ErrorCount, kopiaStats.IgnoredErrorCount) } return kopiaStats, deets, itemsSourcedFromBase, err @@ -459,6 +501,8 @@ func mergeDetails( var addedEntries int for _, man := range mans { + mctx := clues.Add(ctx, "manifest_id", man.ID) + // For now skip snapshots that aren't complete. We will need to revisit this // when we tackle restartability. if len(man.IncompleteReason) > 0 { @@ -467,9 +511,11 @@ func mergeDetails( bID, ok := man.GetTag(kopia.TagBackupID) if !ok { - return errors.Errorf("no backup ID in snapshot manifest with ID %s", man.ID) + return clues.New("no backup ID in snapshot manifest").WithClues(mctx) } + mctx = clues.Add(mctx, "manifest_backup_id", bID) + _, baseDeets, err := getBackupAndDetailsFromID( ctx, model.StableID(bID), @@ -477,18 +523,15 @@ func mergeDetails( detailsStore, ) if err != nil { - return errors.Wrapf(err, "backup fetching base details for backup %s", bID) + return clues.New("fetching base details for backup").WithClues(mctx) } for _, entry := range baseDeets.Items() { rr, err := path.FromDataLayerPath(entry.RepoRef, true) if err != nil { - return errors.Wrapf( - err, - "parsing base item info path %s in backup %s", - entry.RepoRef, - bID, - ) + return clues.New("parsing base item info path"). + WithClues(mctx). + With("repo_ref", entry.RepoRef) // todo: pii } // Although this base has an entry it may not be the most recent. Check @@ -511,11 +554,7 @@ func mergeDetails( // Fixup paths in the item. item := entry.ItemInfo if err := details.UpdateItem(&item, newPath); err != nil { - return errors.Wrapf( - err, - "updating item info for entry from backup %s", - bID, - ) + return clues.New("updating item details").WithClues(mctx) } // TODO(ashmrtn): This may need updated if we start using this merge @@ -540,11 +579,9 @@ func mergeDetails( } if addedEntries != len(shortRefsFromPrevBackup) { - return errors.Errorf( - "incomplete migration of backup details: found %v of %v expected items", - addedEntries, - len(shortRefsFromPrevBackup), - ) + return clues.New("incomplete migration of backup details"). + WithClues(ctx). + WithAll("item_count", addedEntries, "expected_item_count", len(shortRefsFromPrevBackup)) } return nil @@ -558,29 +595,36 @@ func (op *BackupOperation) persistResults( ) error { op.Results.StartedAt = started op.Results.CompletedAt = time.Now() + op.Results.ReadErrors = opStats.readErr + op.Results.WriteErrors = opStats.writeErr op.Status = Completed - if !opStats.started { + + if opStats.readErr != nil || opStats.writeErr != nil { op.Status = Failed + // TODO(keepers): replace with fault.Errors handling. return multierror.Append( errors.New("errors prevented the operation from processing"), opStats.readErr, opStats.writeErr) } + op.Results.BytesRead = opStats.k.TotalHashedBytes + op.Results.BytesUploaded = opStats.k.TotalUploadedBytes + op.Results.ItemsWritten = opStats.k.TotalFileCount + op.Results.ResourceOwners = opStats.resourceCount + + if opStats.gc == nil { + op.Status = Failed + return errors.New("data population never completed") + } + if opStats.readErr == nil && opStats.writeErr == nil && opStats.gc.Successful == 0 { op.Status = NoData } - op.Results.ReadErrors = opStats.readErr - op.Results.WriteErrors = opStats.writeErr - - op.Results.BytesRead = opStats.k.TotalHashedBytes - op.Results.BytesUploaded = opStats.k.TotalUploadedBytes op.Results.ItemsRead = opStats.gc.Successful - op.Results.ItemsWritten = opStats.k.TotalFileCount - op.Results.ResourceOwners = opStats.resourceCount return nil } @@ -592,26 +636,29 @@ func (op *BackupOperation) createBackupModels( snapID string, backupDetails *details.Details, ) error { + ctx = clues.Add(ctx, "snapshot_id", snapID) + if backupDetails == nil { - return errors.New("no backup details to record") + return clues.New("no backup details to record").WithClues(ctx) } detailsID, err := detailsStore.WriteBackupDetails(ctx, backupDetails) if err != nil { - return errors.Wrap(err, "creating backupdetails model") + return clues.Wrap(err, "creating backupDetails model").WithClues(ctx) } + ctx = clues.Add(ctx, "details_id", detailsID) b := backup.New( snapID, detailsID, op.Status.String(), op.Results.BackupID, op.Selectors, op.Results.ReadWrites, op.Results.StartAndEndTime, + op.Errors, ) - err = op.store.Put(ctx, model.BackupSchema, b) - if err != nil { - return errors.Wrap(err, "creating backup model") + if err = op.store.Put(ctx, model.BackupSchema, b); err != nil { + return clues.Wrap(err, "creating backup model").WithClues(ctx) } dur := op.Results.CompletedAt.Sub(op.Results.StartedAt) diff --git a/src/internal/operations/backup_integration_test.go b/src/internal/operations/backup_integration_test.go index f6e63b022..b3ea617d9 100644 --- a/src/internal/operations/backup_integration_test.go +++ b/src/internal/operations/backup_integration_test.go @@ -153,6 +153,8 @@ func runAndCheckBackup( assert.Less(t, int64(0), bo.Results.BytesRead, "bytes read") assert.Less(t, int64(0), bo.Results.BytesUploaded, "bytes uploaded") assert.Equal(t, 1, bo.Results.ResourceOwners, "count of resource owners") + assert.NoError(t, bo.Errors.Err(), "incremental non-recoverable error") + assert.Empty(t, bo.Errors.Errs(), "incremental recoverable/iteration errors") assert.NoError(t, bo.Results.ReadErrors, "errors reading data") assert.NoError(t, bo.Results.WriteErrors, "errors writing data") assert.Equal(t, 1, mb.TimesCalled[events.BackupStart], "backup-start events") @@ -337,7 +339,15 @@ func generateContainerOfItems( dest, collections) - deets, err := gc.RestoreDataCollections(ctx, acct, sel, dest, dataColls) + deets, err := gc.RestoreDataCollections( + ctx, + backup.Version, + acct, + sel, + dest, + control.Options{RestorePermissions: true}, + dataColls, + ) require.NoError(t, err) return deets @@ -616,6 +626,8 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchange() { assert.Greater(t, bo.Results.BytesRead, incBO.Results.BytesRead, "incremental bytes read") assert.Greater(t, bo.Results.BytesUploaded, incBO.Results.BytesUploaded, "incremental bytes uploaded") assert.Equal(t, bo.Results.ResourceOwners, incBO.Results.ResourceOwners, "incremental backup resource owner") + assert.NoError(t, incBO.Errors.Err(), "incremental non-recoverable error") + assert.Empty(t, incBO.Errors.Errs(), "count incremental recoverable/iteration errors") assert.NoError(t, incBO.Results.ReadErrors, "incremental read errors") assert.NoError(t, incBO.Results.WriteErrors, "incremental write errors") assert.Equal(t, 1, incMB.TimesCalled[events.BackupStart], "incremental backup-start events") @@ -633,6 +645,8 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { ctx, flush := tester.NewContext() defer flush() + tester.LogTimeOfTest(suite.T()) + var ( t = suite.T() acct = tester.NewM365Account(t) @@ -803,7 +817,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { { name: "move an email folder to a subfolder", updateUserData: func(t *testing.T) { - // contacts cannot be sufoldered; this is an email-only change + // contacts and events cannot be sufoldered; this is an email-only change toContainer := dataset[path.EmailCategory].dests[container1].containerID fromContainer := dataset[path.EmailCategory].dests[container2].containerID @@ -826,23 +840,22 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { updateUserData: func(t *testing.T) { for category, d := range dataset { containerID := d.dests[container2].containerID - cli := gc.Service.Client().UsersById(suite.user) switch category { case path.EmailCategory: require.NoError( t, - cli.MailFoldersById(containerID).Delete(ctx, nil), + ac.Mail().DeleteContainer(ctx, suite.user, containerID), "deleting an email folder") case path.ContactsCategory: require.NoError( t, - cli.ContactFoldersById(containerID).Delete(ctx, nil), + ac.Contacts().DeleteContainer(ctx, suite.user, containerID), "deleting a contacts folder") case path.EventsCategory: require.NoError( t, - cli.CalendarsById(containerID).Delete(ctx, nil), + ac.Events().DeleteContainer(ctx, suite.user, containerID), "deleting a calendar") } } @@ -923,19 +936,19 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { require.NoError(t, err, "updating contact folder name") case path.EventsCategory: - ccf := cli.CalendarsById(containerID) + cbi := cli.CalendarsById(containerID) - body, err := ccf.Get(ctx, nil) + body, err := cbi.Get(ctx, nil) require.NoError(t, err, "getting calendar") body.SetName(&containerRename) - _, err = ccf.Patch(ctx, body, nil) + _, err = cbi.Patch(ctx, body, nil) require.NoError(t, err, "updating calendar name") } } }, - itemsRead: 0, - itemsWritten: 4, + itemsRead: 0, // containers are not counted as reads + itemsWritten: 4, // two items per category }, { name: "add a new item", @@ -1038,6 +1051,8 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() { // +4 on read/writes to account for metadata: 1 delta and 1 path for each type. assert.Equal(t, test.itemsWritten+4, incBO.Results.ItemsWritten, "incremental items written") assert.Equal(t, test.itemsRead+4, incBO.Results.ItemsRead, "incremental items read") + assert.NoError(t, incBO.Errors.Err(), "incremental non-recoverable error") + assert.Empty(t, incBO.Errors.Errs(), "incremental recoverable/iteration errors") assert.NoError(t, incBO.Results.ReadErrors, "incremental read errors") assert.NoError(t, incBO.Results.WriteErrors, "incremental write errors") assert.Equal(t, 1, incMB.TimesCalled[events.BackupStart], "incremental backup-start events") @@ -1066,7 +1081,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_oneDrive() { sel.Include(sel.AllData()) - bo, _, _, _, closer := prepNewTestBackupOp(t, ctx, mb, sel.Selector, control.Toggles{}) + bo, _, _, _, closer := prepNewTestBackupOp(t, ctx, mb, sel.Selector, control.Toggles{EnablePermissionsBackup: true}) defer closer() runAndCheckBackup(t, ctx, &bo, mb) diff --git a/src/internal/operations/backup_test.go b/src/internal/operations/backup_test.go index 795f341c6..149448e66 100644 --- a/src/internal/operations/backup_test.go +++ b/src/internal/operations/backup_test.go @@ -373,7 +373,6 @@ func (suite *BackupOpSuite) TestBackupOperation_PersistResults() { expectStatus: Completed, expectErr: assert.NoError, stats: backupStats{ - started: true, resourceCount: 1, k: &kopia.BackupStats{ TotalFileCount: 1, @@ -389,7 +388,7 @@ func (suite *BackupOpSuite) TestBackupOperation_PersistResults() { expectStatus: Failed, expectErr: assert.Error, stats: backupStats{ - started: false, + readErr: assert.AnError, k: &kopia.BackupStats{}, gc: &support.ConnectorOperationStatus{}, }, @@ -398,9 +397,8 @@ func (suite *BackupOpSuite) TestBackupOperation_PersistResults() { expectStatus: NoData, expectErr: assert.NoError, stats: backupStats{ - started: true, - k: &kopia.BackupStats{}, - gc: &support.ConnectorOperationStatus{}, + k: &kopia.BackupStats{}, + gc: &support.ConnectorOperationStatus{}, }, }, } @@ -422,11 +420,11 @@ func (suite *BackupOpSuite) TestBackupOperation_PersistResults() { assert.Equal(t, test.expectStatus.String(), op.Status.String(), "status") assert.Equal(t, test.stats.gc.Successful, op.Results.ItemsRead, "items read") - assert.Equal(t, test.stats.readErr, op.Results.ReadErrors, "read errors") assert.Equal(t, test.stats.k.TotalFileCount, op.Results.ItemsWritten, "items written") assert.Equal(t, test.stats.k.TotalHashedBytes, op.Results.BytesRead, "bytes read") assert.Equal(t, test.stats.k.TotalUploadedBytes, op.Results.BytesUploaded, "bytes written") assert.Equal(t, test.stats.resourceCount, op.Results.ResourceOwners, "resource owners") + assert.Equal(t, test.stats.readErr, op.Results.ReadErrors, "read errors") assert.Equal(t, test.stats.writeErr, op.Results.WriteErrors, "write errors") assert.Equal(t, now, op.Results.StartedAt, "started at") assert.Less(t, now, op.Results.CompletedAt, "completed at") @@ -434,258 +432,6 @@ func (suite *BackupOpSuite) TestBackupOperation_PersistResults() { } } -func (suite *BackupOpSuite) TestBackupOperation_VerifyDistinctBases() { - const user = "a-user" - - table := []struct { - name string - input []*kopia.ManifestEntry - errCheck assert.ErrorAssertionFunc - }{ - { - name: "SingleManifestMultipleReasons", - input: []*kopia.ManifestEntry{ - { - Manifest: &snapshot.Manifest{ - ID: "id1", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EventsCategory, - }, - }, - }, - }, - errCheck: assert.NoError, - }, - { - name: "MultipleManifestsDistinctReason", - input: []*kopia.ManifestEntry{ - { - Manifest: &snapshot.Manifest{ - ID: "id1", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - { - Manifest: &snapshot.Manifest{ - ID: "id2", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EventsCategory, - }, - }, - }, - }, - errCheck: assert.NoError, - }, - { - name: "MultipleManifestsSameReason", - input: []*kopia.ManifestEntry{ - { - Manifest: &snapshot.Manifest{ - ID: "id1", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - { - Manifest: &snapshot.Manifest{ - ID: "id2", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - }, - errCheck: assert.Error, - }, - { - name: "MultipleManifestsSameReasonOneIncomplete", - input: []*kopia.ManifestEntry{ - { - Manifest: &snapshot.Manifest{ - ID: "id1", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - { - Manifest: &snapshot.Manifest{ - ID: "id2", - IncompleteReason: "checkpoint", - }, - Reasons: []kopia.Reason{ - { - ResourceOwner: user, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - }, - errCheck: assert.NoError, - }, - } - - for _, test := range table { - suite.T().Run(test.name, func(t *testing.T) { - test.errCheck(t, verifyDistinctBases(test.input)) - }) - } -} - -func (suite *BackupOpSuite) TestBackupOperation_CollectMetadata() { - var ( - tenant = "a-tenant" - resourceOwner = "a-user" - fileNames = []string{ - "delta", - "paths", - } - - emailDeltaPath = makeMetadataPath( - suite.T(), - tenant, - path.ExchangeService, - resourceOwner, - path.EmailCategory, - fileNames[0], - ) - emailPathsPath = makeMetadataPath( - suite.T(), - tenant, - path.ExchangeService, - resourceOwner, - path.EmailCategory, - fileNames[1], - ) - contactsDeltaPath = makeMetadataPath( - suite.T(), - tenant, - path.ExchangeService, - resourceOwner, - path.ContactsCategory, - fileNames[0], - ) - contactsPathsPath = makeMetadataPath( - suite.T(), - tenant, - path.ExchangeService, - resourceOwner, - path.ContactsCategory, - fileNames[1], - ) - ) - - table := []struct { - name string - inputMan *kopia.ManifestEntry - inputFiles []string - expected []path.Path - }{ - { - name: "SingleReasonSingleFile", - inputMan: &kopia.ManifestEntry{ - Manifest: &snapshot.Manifest{}, - Reasons: []kopia.Reason{ - { - ResourceOwner: resourceOwner, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - inputFiles: []string{fileNames[0]}, - expected: []path.Path{emailDeltaPath}, - }, - { - name: "SingleReasonMultipleFiles", - inputMan: &kopia.ManifestEntry{ - Manifest: &snapshot.Manifest{}, - Reasons: []kopia.Reason{ - { - ResourceOwner: resourceOwner, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - }, - }, - inputFiles: fileNames, - expected: []path.Path{emailDeltaPath, emailPathsPath}, - }, - { - name: "MultipleReasonsMultipleFiles", - inputMan: &kopia.ManifestEntry{ - Manifest: &snapshot.Manifest{}, - Reasons: []kopia.Reason{ - { - ResourceOwner: resourceOwner, - Service: path.ExchangeService, - Category: path.EmailCategory, - }, - { - ResourceOwner: resourceOwner, - Service: path.ExchangeService, - Category: path.ContactsCategory, - }, - }, - }, - inputFiles: fileNames, - expected: []path.Path{ - emailDeltaPath, - emailPathsPath, - contactsDeltaPath, - contactsPathsPath, - }, - }, - } - - for _, test := range table { - suite.T().Run(test.name, func(t *testing.T) { - ctx, flush := tester.NewContext() - defer flush() - - mr := &mockRestorer{} - - _, err := collectMetadata(ctx, mr, test.inputMan, test.inputFiles, tenant) - assert.NoError(t, err) - - checkPaths(t, test.expected, mr.gotPaths) - }) - } -} - func (suite *BackupOpSuite) TestBackupOperation_ConsumeBackupDataCollections_Paths() { var ( tenant = "a-tenant" diff --git a/src/internal/operations/manifests.go b/src/internal/operations/manifests.go index fe0e4d09d..c0ba35e43 100644 --- a/src/internal/operations/manifests.go +++ b/src/internal/operations/manifests.go @@ -3,7 +3,7 @@ package operations import ( "context" - multierror "github.com/hashicorp/go-multierror" + "github.com/alcionai/clues" "github.com/kopia/kopia/repo/manifest" "github.com/pkg/errors" @@ -12,6 +12,7 @@ import ( "github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/pkg/backup" + "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/logger" "github.com/alcionai/corso/src/pkg/path" ) @@ -44,6 +45,7 @@ func produceManifestsAndMetadata( reasons []kopia.Reason, tenantID string, getMetadata bool, + errs fault.Adder, ) ([]*kopia.ManifestEntry, []data.Collection, bool, error) { var ( metadataFiles = graph.AllMetadataFileNames() @@ -68,12 +70,10 @@ func produceManifestsAndMetadata( // // TODO(ashmrtn): This may need updating if we start sourcing item backup // details from previous snapshots when using kopia-assisted incrementals. - if err := verifyDistinctBases(ms); err != nil { - logger.Ctx(ctx).Warnw( + if err := verifyDistinctBases(ctx, ms, errs); err != nil { + logger.Ctx(ctx).With("error", err).Infow( "base snapshot collision, falling back to full backup", - "error", - err, - ) + clues.In(ctx).Slice()...) return ms, nil, false, nil } @@ -83,40 +83,41 @@ func produceManifestsAndMetadata( continue } + mctx := clues.Add(ctx, "manifest_id", man.ID) + bID, ok := man.GetTag(kopia.TagBackupID) if !ok { - return nil, nil, false, errors.New("snapshot manifest missing backup ID") + err = clues.New("snapshot manifest missing backup ID").WithClues(ctx) + return nil, nil, false, err } - dID, _, err := gdi.GetDetailsIDFromBackupID(ctx, model.StableID(bID)) + mctx = clues.Add(mctx, "manifest_backup_id", man.ID) + + dID, _, err := gdi.GetDetailsIDFromBackupID(mctx, model.StableID(bID)) if err != nil { // if no backup exists for any of the complete manifests, we want // to fall back to a complete backup. if errors.Is(err, kopia.ErrNotFound) { - logger.Ctx(ctx).Infow( - "backup missing, falling back to full backup", - "backup_id", bID) - + logger.Ctx(ctx).Infow("backup missing, falling back to full backup", clues.In(mctx).Slice()...) return ms, nil, false, nil } return nil, nil, false, errors.Wrap(err, "retrieving prior backup data") } + mctx = clues.Add(mctx, "manifest_details_id", dID) + // if no detailsID exists for any of the complete manifests, we want // to fall back to a complete backup. This is a temporary prevention // mechanism to keep backups from falling into a perpetually bad state. // This makes an assumption that the ID points to a populated set of // details; we aren't doing the work to look them up. if len(dID) == 0 { - logger.Ctx(ctx).Infow( - "backup missing details ID, falling back to full backup", - "backup_id", bID) - + logger.Ctx(ctx).Infow("backup missing details ID, falling back to full backup", clues.In(mctx).Slice()...) return ms, nil, false, nil } - colls, err := collectMetadata(ctx, mr, man, metadataFiles, tenantID) + colls, err := collectMetadata(mctx, mr, man, metadataFiles, tenantID) if err != nil && !errors.Is(err, kopia.ErrNotFound) { // prior metadata isn't guaranteed to exist. // if it doesn't, we'll just have to do a @@ -134,9 +135,9 @@ func produceManifestsAndMetadata( // of manifests, that each manifest's Reason (owner, service, category) is only // included once. If a reason is duplicated by any two manifests, an error is // returned. -func verifyDistinctBases(mans []*kopia.ManifestEntry) error { +func verifyDistinctBases(ctx context.Context, mans []*kopia.ManifestEntry, errs fault.Adder) error { var ( - errs *multierror.Error + failed bool reasons = map[string]manifest.ID{} ) @@ -155,10 +156,11 @@ func verifyDistinctBases(mans []*kopia.ManifestEntry) error { reasonKey := reason.ResourceOwner + reason.Service.String() + reason.Category.String() if b, ok := reasons[reasonKey]; ok { - errs = multierror.Append(errs, errors.Errorf( - "multiple base snapshots source data for %s %s. IDs: %s, %s", - reason.Service, reason.Category, b, man.ID, - )) + failed = true + + errs.Add(clues.New("manifests have overlapping reasons"). + WithClues(ctx). + With("other_manifest_id", b)) continue } @@ -167,7 +169,11 @@ func verifyDistinctBases(mans []*kopia.ManifestEntry) error { } } - return errs.ErrorOrNil() + if failed { + return clues.New("multiple base snapshots qualify").WithClues(ctx) + } + + return nil } // collectMetadata retrieves all metadata files associated with the manifest. @@ -191,7 +197,9 @@ func collectMetadata( reason.Category, true) if err != nil { - return nil, errors.Wrapf(err, "building metadata path") + return nil, clues. + Wrap(err, "building metadata path"). + WithAll("metadata_file", fn, "category", reason.Category) } paths = append(paths, p) diff --git a/src/internal/operations/manifests_test.go b/src/internal/operations/manifests_test.go index 7cfc9ac9a..93cdb982f 100644 --- a/src/internal/operations/manifests_test.go +++ b/src/internal/operations/manifests_test.go @@ -14,6 +14,7 @@ import ( "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/pkg/backup" + "github.com/alcionai/corso/src/pkg/fault/mock" "github.com/alcionai/corso/src/pkg/path" ) @@ -400,7 +401,10 @@ func (suite *OperationsManifestsUnitSuite) TestVerifyDistinctBases() { } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { - err := verifyDistinctBases(test.mans) + ctx, flush := tester.NewContext() + defer flush() + + err := verifyDistinctBases(ctx, test.mans, mock.NewAdder()) test.expect(t, err) }) } @@ -646,6 +650,8 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() { ctx, flush := tester.NewContext() defer flush() + ma := mock.NewAdder() + mans, dcs, b, err := produceManifestsAndMetadata( ctx, &test.mr, @@ -653,7 +659,7 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() { test.reasons, tid, test.getMeta, - ) + ma) test.assertErr(t, err) test.assertB(t, b) @@ -683,3 +689,270 @@ func (suite *OperationsManifestsUnitSuite) TestProduceManifestsAndMetadata() { }) } } + +// --------------------------------------------------------------------------- +// older tests +// --------------------------------------------------------------------------- + +type BackupManifestSuite struct { + suite.Suite +} + +func TestBackupManifestSuite(t *testing.T) { + suite.Run(t, new(BackupOpSuite)) +} + +func (suite *BackupManifestSuite) TestBackupOperation_VerifyDistinctBases() { + const user = "a-user" + + table := []struct { + name string + input []*kopia.ManifestEntry + errCheck assert.ErrorAssertionFunc + }{ + { + name: "SingleManifestMultipleReasons", + input: []*kopia.ManifestEntry{ + { + Manifest: &snapshot.Manifest{ + ID: "id1", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EventsCategory, + }, + }, + }, + }, + errCheck: assert.NoError, + }, + { + name: "MultipleManifestsDistinctReason", + input: []*kopia.ManifestEntry{ + { + Manifest: &snapshot.Manifest{ + ID: "id1", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + { + Manifest: &snapshot.Manifest{ + ID: "id2", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EventsCategory, + }, + }, + }, + }, + errCheck: assert.NoError, + }, + { + name: "MultipleManifestsSameReason", + input: []*kopia.ManifestEntry{ + { + Manifest: &snapshot.Manifest{ + ID: "id1", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + { + Manifest: &snapshot.Manifest{ + ID: "id2", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + }, + errCheck: assert.Error, + }, + { + name: "MultipleManifestsSameReasonOneIncomplete", + input: []*kopia.ManifestEntry{ + { + Manifest: &snapshot.Manifest{ + ID: "id1", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + { + Manifest: &snapshot.Manifest{ + ID: "id2", + IncompleteReason: "checkpoint", + }, + Reasons: []kopia.Reason{ + { + ResourceOwner: user, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + }, + errCheck: assert.NoError, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + ctx, flush := tester.NewContext() + defer flush() + + test.errCheck(t, verifyDistinctBases(ctx, test.input, mock.NewAdder())) + }) + } +} + +func (suite *BackupManifestSuite) TestBackupOperation_CollectMetadata() { + var ( + tenant = "a-tenant" + resourceOwner = "a-user" + fileNames = []string{ + "delta", + "paths", + } + + emailDeltaPath = makeMetadataPath( + suite.T(), + tenant, + path.ExchangeService, + resourceOwner, + path.EmailCategory, + fileNames[0], + ) + emailPathsPath = makeMetadataPath( + suite.T(), + tenant, + path.ExchangeService, + resourceOwner, + path.EmailCategory, + fileNames[1], + ) + contactsDeltaPath = makeMetadataPath( + suite.T(), + tenant, + path.ExchangeService, + resourceOwner, + path.ContactsCategory, + fileNames[0], + ) + contactsPathsPath = makeMetadataPath( + suite.T(), + tenant, + path.ExchangeService, + resourceOwner, + path.ContactsCategory, + fileNames[1], + ) + ) + + table := []struct { + name string + inputMan *kopia.ManifestEntry + inputFiles []string + expected []path.Path + }{ + { + name: "SingleReasonSingleFile", + inputMan: &kopia.ManifestEntry{ + Manifest: &snapshot.Manifest{}, + Reasons: []kopia.Reason{ + { + ResourceOwner: resourceOwner, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + inputFiles: []string{fileNames[0]}, + expected: []path.Path{emailDeltaPath}, + }, + { + name: "SingleReasonMultipleFiles", + inputMan: &kopia.ManifestEntry{ + Manifest: &snapshot.Manifest{}, + Reasons: []kopia.Reason{ + { + ResourceOwner: resourceOwner, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + }, + }, + inputFiles: fileNames, + expected: []path.Path{emailDeltaPath, emailPathsPath}, + }, + { + name: "MultipleReasonsMultipleFiles", + inputMan: &kopia.ManifestEntry{ + Manifest: &snapshot.Manifest{}, + Reasons: []kopia.Reason{ + { + ResourceOwner: resourceOwner, + Service: path.ExchangeService, + Category: path.EmailCategory, + }, + { + ResourceOwner: resourceOwner, + Service: path.ExchangeService, + Category: path.ContactsCategory, + }, + }, + }, + inputFiles: fileNames, + expected: []path.Path{ + emailDeltaPath, + emailPathsPath, + contactsDeltaPath, + contactsPathsPath, + }, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + ctx, flush := tester.NewContext() + defer flush() + + mr := &mockRestorer{} + + _, err := collectMetadata(ctx, mr, test.inputMan, test.inputFiles, tenant) + assert.NoError(t, err) + + checkPaths(t, test.expected, mr.gotPaths) + }) + } +} diff --git a/src/internal/operations/operation.go b/src/internal/operations/operation.go index 24391997e..32122d682 100644 --- a/src/internal/operations/operation.go +++ b/src/internal/operations/operation.go @@ -13,6 +13,7 @@ import ( "github.com/alcionai/corso/src/internal/observe" "github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/control" + "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/store" ) @@ -52,9 +53,11 @@ const ( // Specific processes (eg: backups, restores, etc) are expected to wrap operation // with process specific details. type operation struct { - CreatedAt time.Time `json:"createdAt"` // datetime of the operation's creation - Options control.Options `json:"options"` - Status opStatus `json:"status"` + CreatedAt time.Time `json:"createdAt"` + + Errors *fault.Errors `json:"errors"` + Options control.Options `json:"options"` + Status opStatus `json:"status"` bus events.Eventer kopia *kopia.Wrapper @@ -69,11 +72,14 @@ func newOperation( ) operation { return operation{ CreatedAt: time.Now(), + Errors: fault.New(opts.FailFast), Options: opts, - bus: bus, - kopia: kw, - store: sw, - Status: InProgress, + + bus: bus, + kopia: kw, + store: sw, + + Status: InProgress, } } diff --git a/src/internal/operations/restore.go b/src/internal/operations/restore.go index 3ed84c5f8..f90e3c3c8 100644 --- a/src/internal/operations/restore.go +++ b/src/internal/operations/restore.go @@ -3,6 +3,8 @@ package operations import ( "context" "fmt" + "runtime/debug" + "sort" "time" "github.com/alcionai/clues" @@ -44,7 +46,7 @@ type RestoreOperation struct { // RestoreResults aggregate the details of the results of the operation. type RestoreResults struct { - stats.Errs + stats.Errs // deprecated in place of fault.Errors in the base operation. stats.ReadWrites stats.StartAndEndTime } @@ -89,7 +91,6 @@ type restoreStats struct { gc *support.ConnectorOperationStatus bytesRead *stats.ByteCounter resourceCount int - started bool readErr, writeErr error // a transient value only used to pair up start-end events. @@ -107,9 +108,40 @@ type restorer interface { // Run begins a synchronous restore operation. func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.Details, err error) { - ctx, end := D.Span(ctx, "operations:restore:run") - defer end() + defer func() { + if r := recover(); r != nil { + err = clues.Wrap(r.(error), "panic recovery").WithClues(ctx).With("stacktrace", debug.Stack()) + } + }() + ctx, end := D.Span(ctx, "operations:restore:run") + defer func() { + end() + // wait for the progress display to clean up + observe.Complete() + }() + + ctx = clues.AddAll( + ctx, + "tenant_id", op.account.ID(), // TODO: pii + "backup_id", op.BackupID, + "service", op.Selectors.Service) + + deets, err := op.do(ctx) + if err != nil { + logger.Ctx(ctx). + With("err", err). + Errorw("restore operation", clues.InErr(err).Slice()...) + + return nil, err + } + + logger.Ctx(ctx).Infow("completed restore", "results", op.Results) + + return deets, nil +} + +func (op *RestoreOperation) do(ctx context.Context) (restoreDetails *details.Details, err error) { var ( opStats = restoreStats{ bytesRead: &stats.ByteCounter{}, @@ -119,8 +151,11 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De ) defer func() { - // wait for the progress display to clean up - observe.Complete() + // panic recovery here prevents additional errors in op.persistResults() + if r := recover(); r != nil { + err = clues.Wrap(r.(error), "panic recovery").WithClues(ctx).With("stacktrace", debug.Stack()) + return + } err = op.persistResults(ctx, startTime, &opStats) if err != nil { @@ -130,12 +165,6 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De detailsStore := streamstore.New(op.kopia, op.account.ID(), op.Selectors.PathService()) - ctx = clues.AddAll( - ctx, - "tenant_id", op.account.ID(), // TODO: pii - "backup_id", op.BackupID, - "service", op.Selectors.Service) - bup, deets, err := getBackupAndDetailsFromID( ctx, op.BackupID, @@ -143,10 +172,8 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De detailsStore, ) if err != nil { - err = errors.Wrap(err, "restore") - opStats.readErr = err - - return nil, err + opStats.readErr = errors.Wrap(err, "restore") + return nil, opStats.readErr } ctx = clues.Add(ctx, "resource_owner", bup.Selector.DiscreteOwner) @@ -169,7 +196,6 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De } ctx = clues.Add(ctx, "details_paths", len(paths)) - observe.Message(ctx, observe.Safe(fmt.Sprintf("Discovered %d items in backup %s to restore", len(paths), op.BackupID))) kopiaComplete, closer := observe.MessageWithCompletion(ctx, observe.Safe("Enumerating items in repository")) @@ -178,15 +204,12 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De dcs, err := op.kopia.RestoreMultipleItems(ctx, bup.SnapshotID, paths, opStats.bytesRead) if err != nil { - err = errors.Wrap(err, "retrieving service data") - opStats.readErr = err - - return nil, err + opStats.readErr = errors.Wrap(err, "retrieving service data") + return nil, opStats.readErr } kopiaComplete <- struct{}{} - ctx = clues.Add(ctx, "collections", len(dcs)) - + ctx = clues.Add(ctx, "coll_count", len(dcs)) opStats.cs = dcs opStats.resourceCount = len(data.ResourceOwnerSet(dcs)) @@ -202,19 +225,19 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De restoreDetails, err = gc.RestoreDataCollections( ctx, + bup.Version, op.account, op.Selectors, op.Destination, - dcs) + op.Options, + dcs, + ) if err != nil { - err = errors.Wrap(err, "restoring service data") - opStats.writeErr = err - - return nil, err + opStats.writeErr = errors.Wrap(err, "restoring service data") + return nil, opStats.writeErr } restoreComplete <- struct{}{} - opStats.started = true opStats.gc = gc.AwaitStatus() logger.Ctx(ctx).Debug(gc.PrintableStatus()) @@ -230,10 +253,12 @@ func (op *RestoreOperation) persistResults( ) error { op.Results.StartedAt = started op.Results.CompletedAt = time.Now() + op.Results.ReadErrors = opStats.readErr + op.Results.WriteErrors = opStats.writeErr op.Status = Completed - if !opStats.started { + if opStats.readErr != nil || opStats.writeErr != nil { op.Status = Failed return multierror.Append( @@ -242,17 +267,20 @@ func (op *RestoreOperation) persistResults( opStats.writeErr) } + op.Results.BytesRead = opStats.bytesRead.NumBytes + op.Results.ItemsRead = len(opStats.cs) // TODO: file count, not collection count + op.Results.ResourceOwners = opStats.resourceCount + + if opStats.gc == nil { + op.Status = Failed + return errors.New("data restoration never completed") + } + if opStats.readErr == nil && opStats.writeErr == nil && opStats.gc.Successful == 0 { op.Status = NoData } - op.Results.ReadErrors = opStats.readErr - op.Results.WriteErrors = opStats.writeErr - - op.Results.BytesRead = opStats.bytesRead.NumBytes - op.Results.ItemsRead = len(opStats.cs) // TODO: file count, not collection count op.Results.ItemsWritten = opStats.gc.Successful - op.Results.ResourceOwners = opStats.resourceCount dur := op.Results.CompletedAt.Sub(op.Results.StartedAt) @@ -309,5 +337,20 @@ func formatDetailsForRestoration( paths[i] = p } + // TODO(meain): Move this to onedrive specific component, but as + // of now the paths can technically be from multiple services + + // This sort is done primarily to order `.meta` files after `.data` + // files. This is only a necessity for OneDrive as we are storing + // metadata for files/folders in separate meta files and we the + // data to be restored before we can restore the metadata. + sort.Slice(paths, func(i, j int) bool { + return paths[i].String() < paths[j].String() + }) + + if errs != nil { + return nil, errs + } + return paths, nil } diff --git a/src/internal/operations/restore_test.go b/src/internal/operations/restore_test.go index 44de04c66..9bf21b806 100644 --- a/src/internal/operations/restore_test.go +++ b/src/internal/operations/restore_test.go @@ -57,7 +57,6 @@ func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() { expectStatus: Completed, expectErr: assert.NoError, stats: restoreStats{ - started: true, resourceCount: 1, bytesRead: &stats.ByteCounter{ NumBytes: 42, @@ -73,7 +72,7 @@ func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() { expectStatus: Failed, expectErr: assert.Error, stats: restoreStats{ - started: false, + readErr: assert.AnError, bytesRead: &stats.ByteCounter{}, gc: &support.ConnectorOperationStatus{}, }, @@ -82,7 +81,6 @@ func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() { expectStatus: NoData, expectErr: assert.NoError, stats: restoreStats{ - started: true, bytesRead: &stats.ByteCounter{}, cs: []data.Collection{}, gc: &support.ConnectorOperationStatus{}, @@ -106,10 +104,10 @@ func (suite *RestoreOpSuite) TestRestoreOperation_PersistResults() { assert.Equal(t, test.expectStatus.String(), op.Status.String(), "status") assert.Equal(t, len(test.stats.cs), op.Results.ItemsRead, "items read") - assert.Equal(t, test.stats.readErr, op.Results.ReadErrors, "read errors") assert.Equal(t, test.stats.gc.Successful, op.Results.ItemsWritten, "items written") assert.Equal(t, test.stats.bytesRead.NumBytes, op.Results.BytesRead, "resource owners") assert.Equal(t, test.stats.resourceCount, op.Results.ResourceOwners, "resource owners") + assert.Equal(t, test.stats.readErr, op.Results.ReadErrors, "read errors") assert.Equal(t, test.stats.writeErr, op.Results.WriteErrors, "write errors") assert.Equal(t, now, op.Results.StartedAt, "started at") assert.Less(t, now, op.Results.CompletedAt, "completed at") @@ -295,8 +293,10 @@ func (suite *RestoreOpIntegrationSuite) TestRestore_Run() { assert.Less(t, 0, ro.Results.ItemsWritten, "restored items written") assert.Less(t, int64(0), ro.Results.BytesRead, "bytes read") assert.Equal(t, 1, ro.Results.ResourceOwners, "resource Owners") - assert.Zero(t, ro.Results.ReadErrors, "errors while reading restore data") - assert.Zero(t, ro.Results.WriteErrors, "errors while writing restore data") + assert.NoError(t, ro.Errors.Err(), "non-recoverable error") + assert.Empty(t, ro.Errors.Errs(), "recoverable errors") + assert.NoError(t, ro.Results.ReadErrors, "errors while reading restore data") + assert.NoError(t, ro.Results.WriteErrors, "errors while writing restore data") assert.Equal(t, suite.numItems, ro.Results.ItemsWritten, "backup and restore wrote the same num of items") assert.Equal(t, 1, mb.TimesCalled[events.RestoreStart], "restore-start events") assert.Equal(t, 1, mb.TimesCalled[events.RestoreEnd], "restore-end events") diff --git a/src/internal/tester/storage.go b/src/internal/tester/storage.go index 0cfabba20..3e16ce05e 100644 --- a/src/internal/tester/storage.go +++ b/src/internal/tester/storage.go @@ -29,11 +29,14 @@ func NewPrefixedS3Storage(t *testing.T) storage.Storage { cfg, err := readTestConfig() require.NoError(t, err, "configuring storage from test file") + prefix := testRepoRootPrefix + t.Name() + "-" + now + t.Logf("testing at s3 bucket [%s] prefix [%s]", cfg[TestCfgBucket], prefix) + st, err := storage.NewStorage( storage.ProviderS3, storage.S3Config{ Bucket: cfg[TestCfgBucket], - Prefix: testRepoRootPrefix + t.Name() + "-" + now, + Prefix: prefix, }, storage.CommonConfig{ Corso: credentials.GetCorso(), diff --git a/src/internal/version/version.go b/src/internal/version/version.go index 4a07d07ba..6b1859a80 100644 --- a/src/internal/version/version.go +++ b/src/internal/version/version.go @@ -1,3 +1,29 @@ package version +import ( + "os/exec" + "strings" +) + var Version = "dev" + +func CurrentVersion() string { + if len(Version) == 0 || Version == "dev" { + c, b := exec.Command("git", "describe", "--tag"), new(strings.Builder) + c.Stdout = b + + if err := c.Run(); err != nil { + return "dev" + } + + s := strings.TrimRight(b.String(), "\n") + + if len(s) != 0 { + return "dev-" + s + } + + return "dev" + } + + return Version +} diff --git a/src/pkg/backup/backup.go b/src/pkg/backup/backup.go index 6d73498eb..4422b3a47 100644 --- a/src/pkg/backup/backup.go +++ b/src/pkg/backup/backup.go @@ -10,9 +10,12 @@ import ( "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/stats" + "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/selectors" ) +const Version = 1 + // Backup represents the result of a backup operation type Backup struct { model.BaseModel @@ -31,8 +34,14 @@ type Backup struct { // Selector used in this operation Selector selectors.Selector `json:"selectors"` + // Version represents the version of the backup format + Version int `json:"version"` + + // Errors contains all errors aggregated during a backup operation. + Errors fault.ErrorsData `json:"errors"` + // stats are embedded so that the values appear as top-level properties - stats.Errs + stats.Errs // Deprecated, replaced with Errors. stats.ReadWrites stats.StartAndEndTime } @@ -46,6 +55,7 @@ func New( selector selectors.Selector, rw stats.ReadWrites, se stats.StartAndEndTime, + errs *fault.Errors, ) *Backup { return &Backup{ BaseModel: model.BaseModel{ @@ -59,8 +69,10 @@ func New( DetailsID: detailsID, Status: status, Selector: selector, + Errors: errs.Data(), ReadWrites: rw, StartAndEndTime: se, + Version: Version, } } @@ -102,7 +114,7 @@ type Printable struct { func (b Backup) MinimumPrintable() any { return Printable{ ID: b.ID, - ErrorCount: support.GetNumberOfErrors(b.ReadErrors) + support.GetNumberOfErrors(b.WriteErrors), + ErrorCount: b.errorCount(), StartedAt: b.StartedAt, Status: b.Status, Version: "0", @@ -125,8 +137,7 @@ func (b Backup) Headers() []string { // Values returns the values matching the Headers list for printing // out to a terminal in a columnar display. func (b Backup) Values() []string { - errCount := support.GetNumberOfErrors(b.ReadErrors) + support.GetNumberOfErrors(b.WriteErrors) - status := fmt.Sprintf("%s (%d errors)", b.Status, errCount) + status := fmt.Sprintf("%s (%d errors)", b.Status, b.errorCount()) return []string{ common.FormatTabularDisplayTime(b.StartedAt), @@ -135,3 +146,23 @@ func (b Backup) Values() []string { b.Selector.DiscreteOwner, } } + +func (b Backup) errorCount() int { + var errCount int + + // current tracking + if b.ReadErrors != nil || b.WriteErrors != nil { + return support.GetNumberOfErrors(b.ReadErrors) + support.GetNumberOfErrors(b.WriteErrors) + } + + // future tracking + if b.Errors.Err != nil || len(b.Errors.Errs) > 0 { + if b.Errors.Err != nil { + errCount++ + } + + errCount += len(b.Errors.Errs) + } + + return errCount +} diff --git a/src/pkg/backup/backup_test.go b/src/pkg/backup/backup_test.go index 1ddf4f4a2..8fbf8c62f 100644 --- a/src/pkg/backup/backup_test.go +++ b/src/pkg/backup/backup_test.go @@ -13,6 +13,7 @@ import ( "github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/stats" "github.com/alcionai/corso/src/pkg/backup" + "github.com/alcionai/corso/src/pkg/fault" "github.com/alcionai/corso/src/pkg/selectors" ) @@ -40,6 +41,9 @@ func stubBackup(t time.Time) backup.Backup { DetailsID: "details", Status: "status", Selector: sel.Selector, + Errors: fault.ErrorsData{ + Errs: []error{errors.New("read"), errors.New("write")}, + }, Errs: stats.Errs{ ReadErrors: errors.New("1"), WriteErrors: errors.New("1"), diff --git a/src/pkg/control/options.go b/src/pkg/control/options.go index 9cc5a334a..7348e8fa6 100644 --- a/src/pkg/control/options.go +++ b/src/pkg/control/options.go @@ -6,10 +6,11 @@ import ( // Options holds the optional configurations for a process type Options struct { - Collision CollisionPolicy `json:"-"` - DisableMetrics bool `json:"disableMetrics"` - FailFast bool `json:"failFast"` - ToggleFeatures Toggles `json:"ToggleFeatures"` + Collision CollisionPolicy `json:"-"` + DisableMetrics bool `json:"disableMetrics"` + FailFast bool `json:"failFast"` + RestorePermissions bool `json:"restorePermissions"` + ToggleFeatures Toggles `json:"ToggleFeatures"` } // Defaults provides an Options with the default values set. @@ -74,4 +75,9 @@ type Toggles struct { // DisableIncrementals prevents backups from using incremental lookups, // forcing a new, complete backup of all data regardless of prior state. DisableIncrementals bool `json:"exchangeIncrementals,omitempty"` + + // EnablePermissionsBackup is used to enable backups of item + // permissions. Permission metadata increases graph api call count, + // so disabling their retrieval when not needed is advised. + EnablePermissionsBackup bool `json:"enablePermissionsBackup,omitempty"` } diff --git a/src/pkg/fault/fault.go b/src/pkg/fault/fault.go index f4171ce77..b8f57108b 100644 --- a/src/pkg/fault/fault.go +++ b/src/pkg/fault/fault.go @@ -87,16 +87,19 @@ func (e *Errors) Fail(err error) *Errors { // setErr handles setting errors.err. Sync locking gets // handled upstream of this call. func (e *Errors) setErr(err error) *Errors { - if e.err != nil { - return e.addErr(err) + if e.err == nil { + e.err = err + return e } - e.err = err + e.errs = append(e.errs, err) return e } -// TODO: introduce Adder interface +type Adder interface { + Add(err error) *Errors +} // Add appends the error to the slice of recoverable and // iterated errors (ie: errors.errs). If failFast is true, diff --git a/src/pkg/fault/fault_test.go b/src/pkg/fault/fault_test.go index 3f5ad127c..8fb2981d7 100644 --- a/src/pkg/fault/fault_test.go +++ b/src/pkg/fault/fault_test.go @@ -73,6 +73,8 @@ func (suite *FaultErrorsUnitSuite) TestErr() { suite.T().Run(test.name, func(t *testing.T) { n := fault.New(test.failFast) require.NotNil(t, n) + require.NoError(t, n.Err()) + require.Empty(t, n.Errs()) e := n.Fail(test.fail) require.NotNil(t, e) @@ -90,6 +92,8 @@ func (suite *FaultErrorsUnitSuite) TestFail() { n := fault.New(false) require.NotNil(t, n) + require.NoError(t, n.Err()) + require.Empty(t, n.Errs()) n.Fail(assert.AnError) assert.Error(t, n.Err()) diff --git a/src/pkg/fault/mock/mock.go b/src/pkg/fault/mock/mock.go new file mode 100644 index 000000000..ba560996d --- /dev/null +++ b/src/pkg/fault/mock/mock.go @@ -0,0 +1,17 @@ +package mock + +import "github.com/alcionai/corso/src/pkg/fault" + +// Adder mocks an adder interface for testing. +type Adder struct { + Errs []error +} + +func NewAdder() *Adder { + return &Adder{Errs: []error{}} +} + +func (ma *Adder) Add(err error) *fault.Errors { + ma.Errs = append(ma.Errs, err) + return fault.New(false) +} diff --git a/src/pkg/logger/logger.go b/src/pkg/logger/logger.go index f64febe2e..a6b5aa4dd 100644 --- a/src/pkg/logger/logger.go +++ b/src/pkg/logger/logger.go @@ -6,10 +6,13 @@ import ( "path/filepath" "time" + "github.com/alcionai/clues" "github.com/spf13/cobra" "github.com/spf13/pflag" "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "github.com/alcionai/corso/src/cli/print" ) // Default location for writing logs, initialized in platform specific files @@ -27,6 +30,8 @@ var ( DebugAPI bool readableOutput bool + + LogFile string ) type logLevel int @@ -116,7 +121,9 @@ func PreloadLoggingFlags() (string, string) { } if logfile != "stdout" && logfile != "stderr" { + LogFile = logfile logdir := filepath.Dir(logfile) + print.Info(context.Background(), "Logging to file: "+logfile) err := os.MkdirAll(logdir, 0o755) if err != nil { @@ -264,7 +271,7 @@ func Ctx(ctx context.Context) *zap.SugaredLogger { return singleton(levelOf(llFlag), defaultLogLocation()) } - return l.(*zap.SugaredLogger) + return l.(*zap.SugaredLogger).With(clues.In(ctx).Slice()...) } // transforms the llevel flag value to a logLevel enum diff --git a/src/pkg/repository/repository.go b/src/pkg/repository/repository.go index f8c8d3d49..087b193bc 100644 --- a/src/pkg/repository/repository.go +++ b/src/pkg/repository/repository.go @@ -2,11 +2,12 @@ package repository import ( "context" - "errors" "time" + "github.com/alcionai/clues" "github.com/google/uuid" "github.com/hashicorp/go-multierror" + "github.com/pkg/errors" "github.com/alcionai/corso/src/internal/events" "github.com/alcionai/corso/src/internal/kopia" @@ -88,6 +89,8 @@ func Initialize( s storage.Storage, opts control.Options, ) (Repository, error) { + ctx = clues.AddAll(ctx, "acct_provider", acct.Provider, "storage_provider", s.Provider) + kopiaRef := kopia.NewConn(s) if err := kopiaRef.Initialize(ctx); err != nil { // replace common internal errors so that sdk users can check results with errors.Is() @@ -95,7 +98,7 @@ func Initialize( return nil, ErrorRepoAlreadyExists } - return nil, err + return nil, errors.Wrap(err, "initializing kopia") } // kopiaRef comes with a count of 1 and NewWrapper/NewModelStore bumps it again so safe // to close here. @@ -103,17 +106,17 @@ func Initialize( w, err := kopia.NewWrapper(kopiaRef) if err != nil { - return nil, err + return nil, clues.Stack(err).WithClues(ctx) } ms, err := kopia.NewModelStore(kopiaRef) if err != nil { - return nil, err + return nil, clues.Stack(err).WithClues(ctx) } bus, err := events.NewBus(ctx, s, acct.ID(), opts) if err != nil { - return nil, err + return nil, errors.Wrap(err, "constructing event bus") } repoID := newRepoID(s) @@ -131,7 +134,7 @@ func Initialize( } if err := newRepoModel(ctx, ms, r.ID); err != nil { - return nil, errors.New("setting up repository") + return nil, clues.New("setting up repository").WithClues(ctx) } r.Bus.Event(ctx, events.RepoInit, nil) @@ -150,6 +153,8 @@ func Connect( s storage.Storage, opts control.Options, ) (Repository, error) { + ctx = clues.AddAll(ctx, "acct_provider", acct.Provider, "storage_provider", s.Provider) + // Close/Reset the progress bar. This ensures callers don't have to worry about // their output getting clobbered (#1720) defer observe.Complete() @@ -160,7 +165,7 @@ func Connect( kopiaRef := kopia.NewConn(s) if err := kopiaRef.Connect(ctx); err != nil { - return nil, err + return nil, errors.Wrap(err, "connecting kopia client") } // kopiaRef comes with a count of 1 and NewWrapper/NewModelStore bumps it again so safe // to close here. @@ -168,17 +173,17 @@ func Connect( w, err := kopia.NewWrapper(kopiaRef) if err != nil { - return nil, err + return nil, clues.Stack(err).WithClues(ctx) } ms, err := kopia.NewModelStore(kopiaRef) if err != nil { - return nil, err + return nil, clues.Stack(err).WithClues(ctx) } bus, err := events.NewBus(ctx, s, acct.ID(), opts) if err != nil { - return nil, err + return nil, errors.Wrap(err, "constructing event bus") } rm, err := getRepoModel(ctx, ms) diff --git a/src/pkg/repository/repository_load_test.go b/src/pkg/repository/repository_load_test.go index 5725e5fda..36714df71 100644 --- a/src/pkg/repository/repository_load_test.go +++ b/src/pkg/repository/repository_load_test.go @@ -114,6 +114,7 @@ func runLoadTest( prefix, service string, usersUnderTest []string, bupSel, restSel selectors.Selector, + runRestore bool, ) { //revive:enable:context-as-argument t.Run(prefix+"_load_test_main", func(t *testing.T) { @@ -126,12 +127,33 @@ func runLoadTest( runBackupListLoadTest(t, ctx, r, service, bid) runBackupDetailsLoadTest(t, ctx, r, service, bid, usersUnderTest) + runRestoreLoadTest(t, ctx, r, prefix, service, bid, usersUnderTest, restSel, b, runRestore) + }) +} + +//revive:disable:context-as-argument +func runRestoreLoadTest( + t *testing.T, + ctx context.Context, + r repository.Repository, + prefix, service, backupID string, + usersUnderTest []string, + restSel selectors.Selector, + bup operations.BackupOperation, + runRestore bool, +) { + //revive:enable:context-as-argument + t.Run(prefix+"_load_test_restore", func(t *testing.T) { + if !runRestore { + t.Skip("restore load test is toggled off") + } + dest := tester.DefaultTestRestoreDestination() - rst, err := r.NewRestore(ctx, bid, restSel, dest) + rst, err := r.NewRestore(ctx, backupID, restSel, dest) require.NoError(t, err) - runRestoreLoadTest(t, ctx, rst, service, b.Results.ItemsWritten, usersUnderTest) + doRestoreLoadTest(t, ctx, rst, service, bup.Results.ItemsWritten, usersUnderTest) }) } @@ -162,8 +184,10 @@ func runBackupLoadTest( assert.Less(t, 0, b.Results.ItemsWritten, "items written") assert.Less(t, int64(0), b.Results.BytesUploaded, "bytes uploaded") assert.Equal(t, len(users), b.Results.ResourceOwners, "resource owners") - assert.Zero(t, b.Results.ReadErrors, "read errors") - assert.Zero(t, b.Results.WriteErrors, "write errors") + assert.NoError(t, b.Errors.Err(), "non-recoverable error") + assert.Empty(t, b.Errors.Errs(), "recoverable errors") + assert.NoError(t, b.Results.ReadErrors, "read errors") + assert.NoError(t, b.Results.WriteErrors, "write errors") }) } @@ -240,7 +264,7 @@ func runBackupDetailsLoadTest( } //revive:disable:context-as-argument -func runRestoreLoadTest( +func doRestoreLoadTest( t *testing.T, ctx context.Context, r operations.RestoreOperation, @@ -268,8 +292,10 @@ func runRestoreLoadTest( assert.Less(t, 0, r.Results.ItemsRead, "items read") assert.Less(t, 0, r.Results.ItemsWritten, "items written") assert.Equal(t, len(users), r.Results.ResourceOwners, "resource owners") - assert.Zero(t, r.Results.ReadErrors, "read errors") - assert.Zero(t, r.Results.WriteErrors, "write errors") + assert.NoError(t, r.Errors.Err(), "non-recoverable error") + assert.Empty(t, r.Errors.Errs(), "recoverable errors") + assert.NoError(t, r.Results.ReadErrors, "read errors") + assert.NoError(t, r.Results.WriteErrors, "write errors") assert.Equal(t, expectItemCount, r.Results.ItemsWritten, "backup and restore wrote the same count of items") ensureAllUsersInDetails(t, users, ds, "restore", name) @@ -408,6 +434,7 @@ func (suite *RepositoryLoadTestExchangeSuite) TestExchange() { "all_users", "exchange", suite.usersUnderTest, sel, sel, // same selection for backup and restore + true, ) } @@ -456,6 +483,7 @@ func (suite *RepositoryIndividualLoadTestExchangeSuite) TestExchange() { "single_user", "exchange", suite.usersUnderTest, sel, sel, // same selection for backup and restore + true, ) } @@ -504,6 +532,7 @@ func (suite *RepositoryLoadTestOneDriveSuite) TestOneDrive() { "all_users", "one_drive", suite.usersUnderTest, sel, sel, // same selection for backup and restore + false, ) } @@ -523,7 +552,6 @@ func TestRepositoryIndividualLoadTestOneDriveSuite(t *testing.T) { func (suite *RepositoryIndividualLoadTestOneDriveSuite) SetupSuite() { t := suite.T() - t.Skip("not running onedrive load tests atm") t.Parallel() suite.ctx, suite.repo, suite.acct, suite.st = initM365Repo(t) suite.usersUnderTest = singleUserSet(t) @@ -548,6 +576,7 @@ func (suite *RepositoryIndividualLoadTestOneDriveSuite) TestOneDrive() { "single_user", "one_drive", suite.usersUnderTest, sel, sel, // same selection for backup and restore + false, ) } @@ -596,6 +625,7 @@ func (suite *RepositoryLoadTestSharePointSuite) TestSharePoint() { "all_sites", "share_point", suite.sitesUnderTest, sel, sel, // same selection for backup and restore + false, ) } @@ -640,5 +670,6 @@ func (suite *RepositoryIndividualLoadTestSharePointSuite) TestSharePoint() { "single_site", "share_point", suite.sitesUnderTest, sel, sel, // same selection for backup and restore + false, ) } diff --git a/website/blog/2023-2-4-where-to-store-corso.md b/website/blog/2023-2-4-where-to-store-corso.md new file mode 100644 index 000000000..cdde919b4 --- /dev/null +++ b/website/blog/2023-2-4-where-to-store-corso.md @@ -0,0 +1,118 @@ +--- +slug: where-to-store-corso +title: "Where to store your Corso Repository" +description: "Storage Options for Corso" +authors: nica +tags: [corso, microsoft 365, backups, S3] +date: 2023-2-4 +image: ./images/boxes_web.jpeg +--- + +![image of a large number of packing boxes](./images/boxes_web.jpeg) + +We all know that Corso is a free and open-source tool for creating backups of your Microsoft 365 data. But where does +that data go? + +Corso creates a repository to store your backups, and the default in our documentation is to send that data to AWS S3. +It's possible however to back up to any object storage system that has an S3-compatible API. Let’s talk about some options. + + +## S3-Compatible Object Storage + +A number of other cloud providers aren’t the 500-pound gorilla of AWS but still offer an S3-compatible API. +Some of them include: + +- Google Cloud: One of the largest cloud providers in the world, Google offers +[an S3-compatible API](https://cloud.google.com/storage/docs/interoperability) on top of its Google Cloud Storage (GCS) offering. +- Backblaze: Known for its deep analysis of hard drive failure statistics, Backblaze offers an S3-compatible API for its +B2 Cloud Storage product. They also make the bold claim of costing [significantly less than AWS S3](https://www.backblaze.com/b2/cloud-storage-pricing.html) +(I haven’t evaluated these claims) but Glacier is still cheaper (see below for more details) +- HPE: HPE Greenlake offers S3 compatibility and claims superior performance over S3. If you want to get a sense of how +‘Enterprise’ HPE is, the best writeup I could find of their offerings is [available only as a PDF](https://www.hpe.com/us/en/collaterals/collateral.a50006216.Create-value-from-data-2C-at-scale-E2-80-93-HPE-GreenLake-for-Scality-solution-brief.html). +- Wasabi: Another popular offering, Wasabi has great integration with existing AWS components at a reduced +cost but watch out for the minimum monthly storage charge and the minimum storage duration policy! + +This is an incomplete list, but any S3-compliant storage with immediate retrieval is expected to work with Corso today. + +## Local S3 Testing + +In my own testing, I use [MinIO](https://min.io/) to create a local S3 server and bucket. This has some great advantages +including extremely low latency for testing. Unless you have a significant hardware and software investment to ensure +reliable storage and compute infrastructure, you probably don't want to rely on a MinIO setup as your primary +backup location, but it’s a great way to do a zero-cost test backup that you totally control. + +While there are a number of in-depth tutorials on how to use +[MinIO to run a local S3 server](https://simonjcarr.medium.com/running-s3-object-storage-locally-with-minio-f50540ffc239), +here’s the single script that can run a non-production instance of MinIO within a Docker container (you’ll need Docker +and the AWS CLI as prerequisites) and get you started with Corso quickly: + +```bash +mkdir -p ~\s/minio/data + +docker run \ + -p 9000:9000 \ + -p 9090:9090 \ + --name minio \ + -v ~/minio/data:/data \ + -e "MINIO_ROOT_USER=ROOTNAME" \ + -e "MINIO_ROOT_PASSWORD=CHANGEME123" \ + quay.io/minio/minio server /data --console-address ":9090" +``` + +In a separate window, create a bucket (`corso-backup`) for use with Corso. + +```bash +export AWS_ACCESS_KEY_ID=ROOTNAME +export AWS_SECRET_ACCESS_KEY=CHANGEME123 + +aws s3api create-bucket --bucket corso-backup --endpoint=http://127.0.0.1:9000 +``` + +To connect Corso to a local MinIO server with `[corso repo init](https://corsobackup.io/docs/cli/corso-repo-init-s3/)` +you’ll want to pass the `--disable-tls` flag so that it will accept an `http` connection + +## Reducing Cost With S3 Storage Classes + +AWS S3 offers [storage classes](https://aws.amazon.com/s3/storage-classes/) for a variety of different use cases and +Corso can leverage a number of them, but not all, to reduce the cost of storing data in the cloud. + +By default, Corso works hard to reduce its data footprint. It will compress and deduplicate data at source to reduce the +amount of storage used as well as the amount of network traffic when writing to object storage. Corso also combines +different emails, attachments, etc. into larger objects to make it more cost-effective by reducing the number of API +calls and increasing network throughput as well as making Corso data eligible and cost-effective for some of the other +storage classes described below. + +Stepping away from the default S3 offering (S3 Standard), S3 offers a number of different Glacier (cheap and deep) +storage classes that can help to further reduce the cost for backup and archival workloads. Within the storage classes, +Corso today supports Glacier Instant Retrieval but, because of user responsiveness and metadata requirements, not the +other Glacier variants. + +Glacier Instant Retrieval should provide the best price performance for a backup workload as backup data blobs are +typically written once, with occasional re-compacting, and read infrequently in the case of restore. One should note +that recommendations such as these are always workload dependent and should be verified for your use case. For example, +we would not recommend Glacier Instant Retrieval if you are constantly testing large restores or have heavy +churn in your backups and +limited retention. However, for most typical backup workloads (write mostly, read rarely), Glacier Instant Retrieval +should work just fine and deliver the best price-performance ratio. + +You can configure your storage to use Glacier Instant Retrieval by adding a `.storageconfig` file to the root of your +bucket. If you have configured Corso to store the repository in a sub-folder within your bucket by adding a +`prefix = '[folder name]'` configuration, the `.storageconfig` should go within that folder in the bucket. + +Here’s an example: + +```json +{ + "blobOptions": [ + { "prefix": "p", "storageClass": "GLACIER_IR" }, + { "storageClass": "STANDARD" } + ] +} +``` + +The `"prefix": "p"` parameter is unrelated to the subfolder `prefix` setting mentioned above. It tells Corso to +use the selected storage class for data blobs (named with a `p` prefix). By default, all other objects including +metadata and indices will use the standard storage tier. + +We would love to hear from you if you’ve deployed Corso with a different storage class, an object storage provider not +listed above, or have questions about how to best cost-optimize your setup. Come [find us on Discord](https://discord.gg/63DTTSnuhT)! diff --git a/website/blog/images/boxes_web.jpeg b/website/blog/images/boxes_web.jpeg new file mode 100644 index 000000000..840e96526 Binary files /dev/null and b/website/blog/images/boxes_web.jpeg differ diff --git a/website/docs/setup/configuration.md b/website/docs/setup/configuration.md index 85c99c6bb..d9255f6b7 100644 --- a/website/docs/setup/configuration.md +++ b/website/docs/setup/configuration.md @@ -129,7 +129,9 @@ directory within the container. ## Log Files +Corso generates a unique log file named with its timestamp for every invocation. The default location of Corso's log file is shown below but the location can be overridden by using the `--log-file` flag. +The log file will be appended to if multiple Corso invocations are pointed to the same file. You can also use `stdout` or `stderr` as the `--log-file` location to redirect the logs to "stdout" and "stderr" respectively. diff --git a/website/docs/setup/fault-tolerance.md b/website/docs/setup/fault-tolerance.md new file mode 100644 index 000000000..1771f600a --- /dev/null +++ b/website/docs/setup/fault-tolerance.md @@ -0,0 +1,48 @@ +# Fault tolerance + +Given the millions of objects found in a typical Microsoft 365 tenant, +Corso is optimized for high-performance processing, hardened to +tolerate transient failures and, most importantly, able to restart backups. + +Corso’s fault-tolerance architecture is motivated by Microsoft’s Graph +API variable performance and throttling. Corso follows Microsoft’s +recommend best practices (for example, [correctly decorating API +traffic](https://learn.microsoft.com/en-us/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online#how-to-decorate-your-http-traffic)) +and, in addition, implements a number of optimizations to improve +backup and restore reliability. + +## Recovery from transient failures + +Corso, at the HTTP layer, will retry requests (after a HTTP timeout, +for example) and will respect Graph API’s directives such as the +`retry-after` header to backoff when needed. This allows backups to +succeed in the face of transient or temporary failures. + +## Restarting from permanent API failures + +The Graph API can, for internal reasons, exhibit extended periods of +failures for particular Graph objects. In this scenario, bounded retries +will be ineffective. Unless invoked with the +fail fast option, Corso will skip over these failing objects. For +backups, it will move forward with backing up other objects belonging +to the user and, for restores, it will continue with trying to restore +any remaining objects. If a multi-user backed is in progress (via `*` +or by specifying multiple users with the `—user` argument), Corso will +also continue processing backups for the remaining users. In both +cases, Corso will exit with a non-zero exit code to reflect incomplete +backups or restores. + +On subsequent backup attempts, Corso will try to +minimize the work involved. If the previous backup was successful and +Corso’s stored state tokens haven’t expired, it will use [delta +queries](https://learn.microsoft.com/en-us/graph/delta-query-overview), +wherever supported, to perform incremental backups. + +If the previous backup for a user had resulted in a failure, Corso +uses a variety of fallback mechanisms to reduce the amount of data +downloaded and reduce the number of objects enumerated. For example, with +OneDrive, Corso won't redo downloads of data from Microsoft 365 or +uploads of data to the Corso repository if it had successfully backed +up that OneDrive file as a part of a previously incomplete and failed +backup. Even if the Graph API might not allow Corso to skip +downloading data, Corso can still skip another upload it to the repository. diff --git a/website/docs/setup/repos.md b/website/docs/setup/repos.md index 6dbc62dff..3c2a7c119 100644 --- a/website/docs/setup/repos.md +++ b/website/docs/setup/repos.md @@ -10,9 +10,15 @@ import TabItem from '@theme/TabItem'; import TOCInline from '@theme/TOCInline'; import {Version} from '@site/src/corsoEnv'; -A Corso [repository](../concepts#corso-concepts) stores encrypted copies of your backup data. Corso uses +A Corso [repository](../concepts#corso-concepts) stores encrypted copies of a Microsoft 365 tenant's +backup data. Each repository is configured to store data in an object storage bucket and, optionally, +a user-specified prefix within the bucket. A repository is only meant to store a single tenant's data +but a single object storage bucket can contain multiple repositories if unique `--prefix` options are +specified when initializing a repository. + +Within a repository, Corso uses AES256-GCM-HMAC-SHA256 to encrypt data at rest using keys that are derived from the repository passphrase. -Data in flight is encrypted via TLS. +Data in flight to and from the repositiry is encrypted via TLS. Repositories are supported on the following object storage systems: diff --git a/website/package-lock.json b/website/package-lock.json index 15757ccf8..632819d60 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -11,7 +11,7 @@ "@docusaurus/core": "2.3.0", "@docusaurus/plugin-google-gtag": "^2.3.0", "@docusaurus/preset-classic": "2.3.0", - "@loadable/component": "^5.15.2", + "@loadable/component": "^5.15.3", "@mdx-js/react": "^1.6.22", "animate.css": "^4.1.1", "clsx": "^1.2.1", @@ -24,13 +24,13 @@ "prism-react-renderer": "^1.3.5", "react": "^17.0.2", "react-dom": "^17.0.2", - "sass": "^1.57.1", + "sass": "^1.58.0", "tw-elements": "^1.0.0-alpha13", "wow.js": "^1.2.2" }, "devDependencies": { "@docusaurus/module-type-aliases": "2.3.0", - "@iconify/react": "^4.0.1", + "@iconify/react": "^4.1.0", "autoprefixer": "^10.4.13", "postcss": "^8.4.21", "tailwindcss": "^3.2.4" @@ -2728,9 +2728,9 @@ } }, "node_modules/@iconify/react": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@iconify/react/-/react-4.0.1.tgz", - "integrity": "sha512-/DBJqh5K7W4f+d4kpvyJa/OTpVa3GfgrE9bZFAKP0vIWDr0cvVU9MVvbbkek216w9nLQhpJY/FeJtc6izB1PHw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@iconify/react/-/react-4.1.0.tgz", + "integrity": "sha512-Mf72i3TNNKpKCKxmo7kzqyrUdCgaoljpqtWmtqpqwyxoV4ukhnDsSRNLhf2yBnqGr3cVZsdj/i0FMpXIY0Qk0g==", "dev": true, "dependencies": { "@iconify/types": "^2.0.0" @@ -2818,9 +2818,9 @@ "license": "MIT" }, "node_modules/@loadable/component": { - "version": "5.15.2", - "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.2.tgz", - "integrity": "sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==", + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.3.tgz", + "integrity": "sha512-VOgYgCABn6+/7aGIpg7m0Ruj34tGetaJzt4bQ345FwEovDQZ+dua+NWLmuJKv8rWZyxOUSfoJkmGnzyDXH2BAQ==", "dependencies": { "@babel/runtime": "^7.7.7", "hoist-non-react-statics": "^3.3.1", @@ -2834,7 +2834,7 @@ "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": ">=16.3.0" + "react": "^16.3.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@mdx-js/mdx": { @@ -7999,10 +7999,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "license": "BSD-2-Clause" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-deceiver": { "version": "1.2.7", @@ -11861,9 +11860,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.57.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", - "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", + "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -16330,9 +16329,9 @@ } }, "@iconify/react": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@iconify/react/-/react-4.0.1.tgz", - "integrity": "sha512-/DBJqh5K7W4f+d4kpvyJa/OTpVa3GfgrE9bZFAKP0vIWDr0cvVU9MVvbbkek216w9nLQhpJY/FeJtc6izB1PHw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@iconify/react/-/react-4.1.0.tgz", + "integrity": "sha512-Mf72i3TNNKpKCKxmo7kzqyrUdCgaoljpqtWmtqpqwyxoV4ukhnDsSRNLhf2yBnqGr3cVZsdj/i0FMpXIY0Qk0g==", "dev": true, "requires": { "@iconify/types": "^2.0.0" @@ -16396,9 +16395,9 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "@loadable/component": { - "version": "5.15.2", - "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.2.tgz", - "integrity": "sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==", + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.3.tgz", + "integrity": "sha512-VOgYgCABn6+/7aGIpg7m0Ruj34tGetaJzt4bQ345FwEovDQZ+dua+NWLmuJKv8rWZyxOUSfoJkmGnzyDXH2BAQ==", "requires": { "@babel/runtime": "^7.7.7", "hoist-non-react-statics": "^3.3.1", @@ -19958,9 +19957,9 @@ } }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "http-deceiver": { "version": "1.2.7", @@ -22452,9 +22451,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass": { - "version": "1.57.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", - "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", + "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", diff --git a/website/package.json b/website/package.json index 4f64d0b6f..08e24f415 100644 --- a/website/package.json +++ b/website/package.json @@ -17,7 +17,7 @@ "@docusaurus/core": "2.3.0", "@docusaurus/plugin-google-gtag": "^2.3.0", "@docusaurus/preset-classic": "2.3.0", - "@loadable/component": "^5.15.2", + "@loadable/component": "^5.15.3", "@mdx-js/react": "^1.6.22", "animate.css": "^4.1.1", "clsx": "^1.2.1", @@ -30,13 +30,13 @@ "prism-react-renderer": "^1.3.5", "react": "^17.0.2", "react-dom": "^17.0.2", - "sass": "^1.57.1", + "sass": "^1.58.0", "tw-elements": "^1.0.0-alpha13", "wow.js": "^1.2.2" }, "devDependencies": { "@docusaurus/module-type-aliases": "2.3.0", - "@iconify/react": "^4.0.1", + "@iconify/react": "^4.1.0", "autoprefixer": "^10.4.13", "postcss": "^8.4.21", "tailwindcss": "^3.2.4" diff --git a/website/sidebars.js b/website/sidebars.js index fd92ea50e..2403412b7 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -19,8 +19,8 @@ const sidebars = { 'quickstart', { type: 'category', - label: 'Corso setup', - items: ['setup/concepts', 'setup/download', 'setup/m365-access', 'setup/configuration', 'setup/repos'], + label: 'Usage', + items: ['setup/concepts', 'setup/download', 'setup/m365-access', 'setup/configuration', 'setup/repos', 'setup/fault-tolerance'], }, { type: 'category', diff --git a/website/styles/Vocab/Base/accept.txt b/website/styles/Vocab/Base/accept.txt index eae43d149..8831b2ca6 100644 --- a/website/styles/Vocab/Base/accept.txt +++ b/website/styles/Vocab/Base/accept.txt @@ -36,4 +36,7 @@ Atlassian SLAs runbooks stdout -stderr \ No newline at end of file +stderr +backoff +Greenlake +subfolder \ No newline at end of file