Harden the Google Analytics account fetch
Three defects, all found reviewing the rebased branch. The connection probe hit /v1alpha/accounts, which any analytics.readonly grant can call, while the driver's first request is the account's accessBindings — that additionally needs Administrator on the account and the manage.users.readonly scope. An Editor connecting, or a user declining the second scope on Google's granular consent screen, probed green and then 403'd on every campaign fetch, leaving the source permanently "Connected" with no rows. The probe now targets the same accessBindings collection the driver reads. A single unreadable property aborted the whole account. A property the token cannot see, or one deleted between the list and the read, threw away every binding already collected; 49 of 50 readable properties are still worth reviewing, so 403 and 404 now skip that property. Anything else still fails the fetch. Fan-out errors named no resource: the account call, the property list and each per-property call all returned the same "unexpected status" string, so a 403 on one subproperty out of forty was unattributable. Errors now carry the account or property ID. The cassette gains a subproperty parented to another property (only reachable through the ancestor filter, so it pins the hierarchy walk that the filter change claimed) and a property returning 403. Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -50,7 +50,12 @@ func googleAnalyticsRegistration() *Registration {
|
||||
"https://www.googleapis.com/auth/analytics.readonly",
|
||||
"https://www.googleapis.com/auth/analytics.manage.users.readonly",
|
||||
},
|
||||
ProbeURL: "https://analyticsadmin.googleapis.com/v1alpha/accounts?pageSize=1",
|
||||
// BuildProbeURL targets the selected account's accessBindings rather
|
||||
// than the accounts list: listing accounts only needs
|
||||
// analytics.readonly, so a non-Administrator connection (or one where
|
||||
// the user declined manage.users.readonly on Google's granular consent
|
||||
// screen) would probe green and then 403 on every fetch.
|
||||
BuildProbeURL: buildGoogleAnalyticsProbeURL,
|
||||
NewDriver: func(_ context.Context, c *http.Client, conn *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
||||
s, err := coredata.ConnectorSettings[coredata.GoogleAnalyticsConnectorSettings](conn)
|
||||
if err != nil {
|
||||
|
||||
@@ -642,6 +642,22 @@ func buildSegmentProbeURL(conn *coredata.Connector) (string, error) {
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
// buildGoogleAnalyticsProbeURL targets the selected account's accessBindings,
|
||||
// the driver's first call, so the probe fails for a connection that can list
|
||||
// accounts but cannot read access bindings.
|
||||
func buildGoogleAnalyticsProbeURL(conn *coredata.Connector) (string, error) {
|
||||
s, err := coredata.ConnectorSettings[coredata.GoogleAnalyticsConnectorSettings](conn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot read google analytics connector settings: %w", err)
|
||||
}
|
||||
|
||||
if s.AccountID == "" {
|
||||
return "", fmt.Errorf("missing google analytics account ID")
|
||||
}
|
||||
|
||||
return drivers.GoogleAnalyticsAccountBindingsProbeURL(s.AccountID)
|
||||
}
|
||||
|
||||
// probeSquare checks a Square credential (OAuth Bearer token or Personal Access
|
||||
// Token) with a GET /v2/merchants/me, sending the required Square-Version
|
||||
// header. The endpoint returns 401 on a dead token and works for both OAuth and
|
||||
|
||||
Reference in New Issue
Block a user