## Description A couple minor refactors. First, combines the graph/service_helper.go and graph/service.go files into a single file (just lift'n'shift, no logic changes). Second, renames CreateHTTPClient to just HTTPClient. Third, replaces the new LargeItemClient constructor with extensible options for the http client, starting with a NoTimeout option. This will provide longer term maintenance over multiple constructors. This change sets up QoL for building multiple services and clients within api layer handlers, which will appear in an immediately following PR. ## Does this PR need a docs update or release note? - [x] ⛔ No ## Type of change - [x] 🧹 Tech Debt/Cleanup ## Issue(s) * #2299 ## Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
188 lines
4.9 KiB
Go
188 lines
4.9 KiB
Go
// getItem.go is a source file designed to retrieve an m365 object from an
|
|
// existing M365 account. Data displayed is representative of the current
|
|
// serialization abstraction versioning used by Microsoft Graph and stored by Corso.
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/microsoft/kiota-abstractions-go/serialization"
|
|
kw "github.com/microsoft/kiota-serialization-json-go"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/cobra"
|
|
|
|
. "github.com/alcionai/corso/src/cli/print"
|
|
"github.com/alcionai/corso/src/cli/utils"
|
|
"github.com/alcionai/corso/src/internal/common"
|
|
"github.com/alcionai/corso/src/internal/connector"
|
|
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
|
"github.com/alcionai/corso/src/internal/connector/graph"
|
|
"github.com/alcionai/corso/src/pkg/account"
|
|
"github.com/alcionai/corso/src/pkg/backup/details"
|
|
"github.com/alcionai/corso/src/pkg/credentials"
|
|
"github.com/alcionai/corso/src/pkg/logger"
|
|
"github.com/alcionai/corso/src/pkg/path"
|
|
)
|
|
|
|
var getCmd = &cobra.Command{
|
|
Use: "get",
|
|
Short: "Get a M365ID item JSON",
|
|
RunE: handleGetCommand,
|
|
}
|
|
|
|
// Required inputs from user for command execution
|
|
var (
|
|
tenant, user, m365ID, category string
|
|
)
|
|
|
|
// main function will produce the JSON String for a given m365 object of a
|
|
// user. Displayed Objects can be used as inputs for Mockable data
|
|
// Supports:
|
|
// - exchange (contacts, email, and events)
|
|
// Input: go run ./getItem.go --user <user>
|
|
//
|
|
// --m365ID <m365ID> --category <oneof: contacts, email, events>
|
|
func main() {
|
|
ctx, _ := logger.SeedLevel(context.Background(), logger.Development)
|
|
ctx = SetRootCmd(ctx, getCmd)
|
|
|
|
defer logger.Flush(ctx)
|
|
|
|
fs := getCmd.PersistentFlags()
|
|
fs.StringVar(&user, "user", "", "m365 user id of M365 user")
|
|
fs.StringVar(&tenant, "tenant", "",
|
|
"m365 Tenant: m365 identifier for the tenant, not required if active in OS Environment")
|
|
fs.StringVar(&m365ID, "m365ID", "", "m365 identifier for object to be created")
|
|
fs.StringVar(&category, "category", "", "type of M365 data (contacts, email, events or files)") // files not supported
|
|
|
|
cobra.CheckErr(getCmd.MarkPersistentFlagRequired("user"))
|
|
cobra.CheckErr(getCmd.MarkPersistentFlagRequired("m365ID"))
|
|
cobra.CheckErr(getCmd.MarkPersistentFlagRequired("category"))
|
|
|
|
if err := getCmd.ExecuteContext(ctx); err != nil {
|
|
logger.Flush(ctx)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func handleGetCommand(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
|
|
if utils.HasNoFlagsAndShownHelp(cmd) {
|
|
return nil
|
|
}
|
|
|
|
_, creds, err := getGC(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = runDisplayM365JSON(ctx, creds, user, m365ID)
|
|
if err != nil {
|
|
return Only(ctx, errors.Wrapf(err, "unable to create mock from M365: %s", m365ID))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runDisplayM365JSON(
|
|
ctx context.Context,
|
|
creds account.M365Config,
|
|
user, itemID string,
|
|
) error {
|
|
var (
|
|
bs []byte
|
|
err error
|
|
cat = path.ToCategoryType(category)
|
|
sw = kw.NewJsonSerializationWriter()
|
|
)
|
|
|
|
ac, err := api.NewClient(creds)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch cat {
|
|
case path.EmailCategory:
|
|
bs, err = getItem(ctx, ac.Mail(), user, itemID)
|
|
case path.EventsCategory:
|
|
bs, err = getItem(ctx, ac.Events(), user, itemID)
|
|
case path.ContactsCategory:
|
|
bs, err = getItem(ctx, ac.Contacts(), user, itemID)
|
|
default:
|
|
return fmt.Errorf("unable to process category: %s", cat)
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
str := string(bs)
|
|
|
|
err = sw.WriteStringValue("", &str)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "unable to %s to string value", itemID)
|
|
}
|
|
|
|
array, err := sw.GetSerializedContent()
|
|
if err != nil {
|
|
return errors.Wrapf(err, "unable to serialize new value from M365:%s", itemID)
|
|
}
|
|
|
|
fmt.Println(string(array))
|
|
|
|
return nil
|
|
}
|
|
|
|
type itemer interface {
|
|
GetItem(
|
|
ctx context.Context,
|
|
user, itemID string,
|
|
) (serialization.Parsable, *details.ExchangeInfo, error)
|
|
Serialize(
|
|
ctx context.Context,
|
|
item serialization.Parsable,
|
|
user, itemID string,
|
|
) ([]byte, error)
|
|
}
|
|
|
|
func getItem(
|
|
ctx context.Context,
|
|
itm itemer,
|
|
user, itemID string,
|
|
) ([]byte, error) {
|
|
sp, _, err := itm.GetItem(ctx, user, itemID)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "getting item")
|
|
}
|
|
|
|
return itm.Serialize(ctx, sp, user, itemID)
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// Helpers
|
|
//-------------------------------------------------------------------------------
|
|
|
|
func getGC(ctx context.Context) (*connector.GraphConnector, account.M365Config, error) {
|
|
// get account info
|
|
m365Cfg := account.M365Config{
|
|
M365: credentials.GetM365(),
|
|
AzureTenantID: common.First(tenant, os.Getenv(account.AzureTenantID)),
|
|
}
|
|
|
|
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
|
|
if err != nil {
|
|
return nil, m365Cfg, Only(ctx, errors.Wrap(err, "finding m365 account details"))
|
|
}
|
|
|
|
gc, err := connector.NewGraphConnector(ctx, graph.HTTPClient(graph.NoTimeout()), acct, connector.Users)
|
|
if err != nil {
|
|
return nil, m365Cfg, Only(ctx, errors.Wrap(err, "connecting to graph API"))
|
|
}
|
|
|
|
return gc, m365Cfg, nil
|
|
}
|