Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion providers/goTo.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
package providers

const GoTo Provider = "goTo"
import "github.com/amp-labs/connectors/common"

const (
GoTo Provider = "goTo"
// ModuleGoTo covers the api.getgo.com base URL, which serves multiple GoTo
// products (admin, meetings, webinars, etc). We name it just "goTo" so users
// don't have to guess which specific product it maps to.
ModuleGoTo common.ModuleID = "goTo"
ModuleGoToConnect common.ModuleID = "goToConnect"
)

func init() {

Check failure on line 14 in providers/goTo.go

View workflow job for this annotation

GitHub Actions / lint

Function 'init' is too long (66 > 60) (funlen)

Check failure on line 14 in providers/goTo.go

View workflow job for this annotation

GitHub Actions / lint

Function 'init' is too long (66 > 60) (funlen)
SetInfo(GoTo, ProviderInfo{
DisplayName: "GoTo",
AuthType: Oauth2,
Expand Down Expand Up @@ -39,5 +48,34 @@
Subscribe: false,
Write: false,
},
PostAuthInfoNeeded: true,
Metadata: &ProviderMetadata{
PostAuthentication: []MetadataItemPostAuthentication{
{

Check failure on line 54 in providers/goTo.go

View workflow job for this annotation

GitHub Actions / lint

MetadataItemPostAuthentication in multi-module provider must have ModuleDependencies set to non-nil value (modulelinter)

Check failure on line 54 in providers/goTo.go

View workflow job for this annotation

GitHub Actions / lint

MetadataItemPostAuthentication in multi-module provider must have ModuleDependencies set to non-nil value (modulelinter)
Name: "accountKey",
},
},
},
DefaultModule: ModuleGoTo,
Modules: &Modules{
ModuleGoTo: {
BaseURL: "https://api.getgo.com",
DisplayName: "GoTo",
Support: Support{
Read: false,
Subscribe: false,
Write: false,
},
},
ModuleGoToConnect: {
BaseURL: "https://api.goto.com",
DisplayName: "GoTo Connect",
Support: Support{
Read: false,
Subscribe: false,
Write: false,
},
},
},
})
}
65 changes: 65 additions & 0 deletions providers/goto/authmetadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package gotoconn

import (
"context"
"strconv"

"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/common/urlbuilder"
)

func (c *Connector) GetPostAuthInfo(ctx context.Context) (*common.PostAuthInfo, error) {
accountKey, err := c.retrieveAccountKey(ctx)
if err != nil {
return nil, err
}

c.accountKey = accountKey

catalogVars := map[string]string{
"accountKey": accountKey,
}

return &common.PostAuthInfo{
CatalogVars: &catalogVars,
}, nil
Comment thread
immdipu marked this conversation as resolved.
}
Comment thread
immdipu marked this conversation as resolved.

func (c *Connector) retrieveAccountKey(ctx context.Context) (string, error) {
url, err := c.getMeURL()
if err != nil {
return "", err
}

resp, err := c.JSONHTTPClient().Get(ctx, url.String())
if err != nil {
return "", err
}

data, err := common.UnmarshalJSON[map[string]any](resp)
if err != nil {
return "", common.ErrFailedToUnmarshalBody
}

if data == nil {
Comment thread
immdipu marked this conversation as resolved.
return "", common.ErrMissingExpectedValues
}

rawAccountKey, ok := (*data)["accountKey"]
if !ok {
return "", common.ErrMissingExpectedValues
}

switch v := rawAccountKey.(type) {
case string:
return v, nil
case float64:
return strconv.FormatInt(int64(v), 10), nil
default:
return "", common.ErrMissingExpectedValues
}
Comment thread
immdipu marked this conversation as resolved.
}

func (c *Connector) getMeURL() (*urlbuilder.URL, error) {
return urlbuilder.New(c.ProviderInfo().BaseURL, "/admin/rest/v1/me")
}
18 changes: 18 additions & 0 deletions providers/goto/authmetamodel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package gotoconn

type AuthMetadataVars struct {
AccountKey string
}

// NewAuthMetadataVars parses map into the model.
func NewAuthMetadataVars(dictionary map[string]string) *AuthMetadataVars {
return &AuthMetadataVars{
AccountKey: dictionary["accountKey"],
}
}

func (v AuthMetadataVars) AsMap() *map[string]string {
return &map[string]string{
"accountKey": v.AccountKey,
}
}
40 changes: 40 additions & 0 deletions providers/goto/connector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Package gotoconn implements the GoTo connector.
//
// The package is named "gotoconn" instead of "goto" because "goto" is a
// reserved keyword in Go and cannot be used as a package identifier. The
// "conn" suffix is short for "connector".
package gotoconn

import (
"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/internal/components"
"github.com/amp-labs/connectors/providers"
)

type Connector struct {
// Basic connector
*components.Connector

// Require authenticated client & account
common.RequireAuthenticatedClient
common.PostAuthInfo

accountKey string
}

func NewConnector(params common.ConnectorParams) (*Connector, error) {
conn, err := components.Initialize(providers.GoTo, params, constructor)
if err != nil {
return nil, err
}

authMetadata := NewAuthMetadataVars(params.Metadata)

conn.accountKey = authMetadata.AccountKey

return conn, nil
}

func constructor(base *components.Connector) (*Connector, error) {
return &Connector{Connector: base}, nil
}
33 changes: 33 additions & 0 deletions test/goto/auth-metadata/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"context"
"log/slog"
"os/signal"
"syscall"

"github.com/amp-labs/connectors/providers/goto"
connTest "github.com/amp-labs/connectors/test/goto"
"github.com/amp-labs/connectors/test/utils"
)

func main() {
// Handle Ctrl-C gracefully.
ctx, done := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer done()

// Set up slog logging.
utils.SetupLogging()

conn := connTest.GetGoToConnector(ctx)

info, err := conn.GetPostAuthInfo(ctx)
if err != nil || info.CatalogVars == nil {
utils.Fail("error obtaining auth info", "error", err)
}

accountKey := gotoconn.NewAuthMetadataVars(*info.CatalogVars).AccountKey

// Log the retrieved account key.
slog.Info("retrieved auth metadata", "account key", accountKey)
}
Comment thread
immdipu marked this conversation as resolved.
51 changes: 51 additions & 0 deletions test/goto/connector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package goto_test

import (
"context"
"net/http"

"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/common/scanning/credscanning"
"github.com/amp-labs/connectors/providers"
"github.com/amp-labs/connectors/providers/goto"
"github.com/amp-labs/connectors/test/utils"
"golang.org/x/oauth2"
)

func GetGoToConnector(ctx context.Context) *gotoconn.Connector {
filePath := credscanning.LoadPath(providers.GoTo)
reader := utils.MustCreateProvCredJSON(filePath, true)

client, err := common.NewOAuthHTTPClient(ctx,
common.WithOAuthClient(http.DefaultClient),
common.WithOAuthConfig(getConfig(reader)),
common.WithOAuthToken(reader.GetOauthToken()),
)
if err != nil {
utils.Fail(err.Error())
}

conn, err := gotoconn.NewConnector(common.ConnectorParams{
AuthenticatedClient: client,
})
if err != nil {
utils.Fail("create goto connector", "error: ", err)
Comment thread
immdipu marked this conversation as resolved.
}

return conn
}

func getConfig(reader *credscanning.ProviderCredentials) *oauth2.Config {
cfg := &oauth2.Config{
ClientID: reader.Get(credscanning.Fields.ClientId),
ClientSecret: reader.Get(credscanning.Fields.ClientSecret),
RedirectURL: "https://dev-api.withampersand.com/callbacks/v1/oauth",
Endpoint: oauth2.Endpoint{
AuthURL: "https://authentication.logmeininc.com/oauth/authorize",
TokenURL: "https://authentication.logmeininc.com/oauth/token",
AuthStyle: oauth2.AuthStyleInParams,
},
}

return cfg
}
Loading