Skip to content

Conversation

@aldevv
Copy link
Contributor

@aldevv aldevv commented Jan 23, 2026

Summary by CodeRabbit

  • New Features

    • Added Multi-Factor Authentication (MFA) support when creating Tableau user accounts.
    • Added option to specify which SAML identity provider configuration to use, with automatic selection when only one exists.
    • Improved handling for environments with multiple identity provider configurations.
  • Style

    • Minor formatting cleanup to an existing role description.

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Jan 23, 2026

@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

Walkthrough

Adds MFA and SAML IDP configuration support to the Tableau connector: new account schema fields, IDP selection logic during account creation, client API to list site IDP configurations, and related model extensions.

Changes

Cohort / File(s) Summary
Connector Schema
pkg/connector/connector.go
Added account creation fields withMFA (bool) and idpConfigurationName (string) to the Tableau connector schema.
Account Creation & IDP Selection
pkg/connector/user.go
Added selectIDPConfiguration() and helpers (findIDPByName, buildMultipleIDPError), read withMFA, set auth_setting when appropriate, include idpConfigurationId when resolved, and improved error handling.
Tableau API Client
pkg/tableau/client.go
Refactored AddUserToSite() to build a user payload including conditional idpConfigurationId or authSetting. Added ListIdpConfigurations(ctx) to fetch site auth configurations.
Data Models
pkg/tableau/models.go
Added AuthSetting to User, expanded CreateUserRequest with AuthSetting and IdpConfigurationId, and introduced IdpConfiguration type (IdpConfigurationId, IdpConfigurationName, AuthSetting, Enabled).

Sequence Diagram

sequenceDiagram
    participant User
    participant Connector
    participant Client as Tableau API Client
    participant Site as Tableau Site

    User->>Connector: Request account creation (withMFA?, idpConfigurationName?)
    Connector->>Connector: Read withMFA and idpConfigurationName

    alt withMFA == true
        Connector->>Connector: set authSetting = "TableauIDWithMFA"
    else withMFA == false
        Connector->>Client: ListIdpConfigurations(ctx)
        Client->>Site: GET /sites/{siteId}/site-auth-configurations
        Site-->>Client: return idp configurations
        Client-->>Connector: list of IdpConfiguration
        alt one enabled SAML IDP
            Connector->>Connector: choose that IdP id
        else idpConfigurationName provided
            Connector->>Connector: find matching IdP by name
        else multiple IDPs & no name
            Connector-->>User: error (specify idpConfigurationName)
        end
    end

    Connector->>Client: AddUserToSite(user{email,siteRole,authSetting?,idpConfigurationId?})
    Client->>Site: POST /sites/{siteId}/users
    Site-->>Client: user created
    Client-->>Connector: success
    Connector-->>User: account created / error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I twitch my nose at auth’s new art,
MFA and SAML play their part,
I hop through configs, one or many,
Name the IDP — or choose the penny,
Hooray! New paths for every heart. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'add SAML as default when creating user' accurately describes the main functionality: enabling SAML/IdP configuration selection during user creation with MFA as a fallback, matching the core changes across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@pkg/connector/user.go`:
- Around line 224-233: The function buildMultipleIDPError builds a dynamic error
message into builder and then calls fmt.Errorf(builder.String()), which is
unsafe for non-constant format strings; replace the final
fmt.Errorf(builder.String()) with errors.New(builder.String()) (or
fmt.Errorf("%s", builder.String())) and add the "errors" import to the file so
the function returns a plain error created from the constructed string;
reference buildMultipleIDPError and the final return statement to locate and
update the code.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@pkg/connector/user.go`:
- Around line 178-195: The code currently returns the sole
enabledSAMLConfigs[0].IdpConfigurationId without honoring idpConfigName; change
the logic in the selection block so that when len(enabledSAMLConfigs) == 1 you
still check idpConfigName: if idpConfigName is empty, return
enabledSAMLConfigs[0].IdpConfigurationId, otherwise call
findIDPByName(enabledSAMLConfigs, idpConfigName) and return an InvalidArgument
error (use uhttp.WrapErrors with buildMultipleIDPError) if the name doesn't
match, otherwise return the matched selectedConfig.IdpConfigurationId; this
preserves current behavior for empty names but surfaces typos/misconfigurations
when a name is provided.

Comment on lines +178 to +195
if len(enabledSAMLConfigs) == 0 {
return "", fmt.Errorf("baton-tableau: you need to pass the MFA flag since no IDP is configured in Tableau")
}

if len(enabledSAMLConfigs) == 1 {
return enabledSAMLConfigs[0].IdpConfigurationId, nil
}

if idpConfigName == "" {
return "", uhttp.WrapErrors(codes.InvalidArgument, "multiple SAML IDPs available", buildMultipleIDPError(enabledSAMLConfigs))
}

selectedConfig, err := findIDPByName(enabledSAMLConfigs, idpConfigName)
if err != nil {
return "", uhttp.WrapErrors(codes.InvalidArgument, fmt.Sprintf("IDP configuration '%s' not found", idpConfigName), buildMultipleIDPError(enabledSAMLConfigs))
}

return selectedConfig.IdpConfigurationId, nil
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Honor explicit idpConfigurationName even when only one config exists.
If a caller provides idpConfigurationName but there’s only one enabled SAML config, the current logic ignores the name and silently selects the only config. That can mask typos or misconfigurations.

🔧 Suggested adjustment
-	if len(enabledSAMLConfigs) == 1 {
-		return enabledSAMLConfigs[0].IdpConfigurationId, nil
-	}
-
-	if idpConfigName == "" {
-		return "", uhttp.WrapErrors(codes.InvalidArgument, "multiple SAML IDPs available", buildMultipleIDPError(enabledSAMLConfigs))
-	}
-
-	selectedConfig, err := findIDPByName(enabledSAMLConfigs, idpConfigName)
-	if err != nil {
-		return "", uhttp.WrapErrors(codes.InvalidArgument, fmt.Sprintf("IDP configuration '%s' not found", idpConfigName), buildMultipleIDPError(enabledSAMLConfigs))
-	}
-
-	return selectedConfig.IdpConfigurationId, nil
+	if idpConfigName != "" {
+		selectedConfig, err := findIDPByName(enabledSAMLConfigs, idpConfigName)
+		if err != nil {
+			return "", uhttp.WrapErrors(codes.InvalidArgument, fmt.Sprintf("IDP configuration '%s' not found", idpConfigName), buildMultipleIDPError(enabledSAMLConfigs))
+		}
+		return selectedConfig.IdpConfigurationId, nil
+	}
+
+	if len(enabledSAMLConfigs) == 1 {
+		return enabledSAMLConfigs[0].IdpConfigurationId, nil
+	}
+
+	return "", uhttp.WrapErrors(codes.InvalidArgument, "multiple SAML IDPs available", buildMultipleIDPError(enabledSAMLConfigs))
🤖 Prompt for AI Agents
In `@pkg/connector/user.go` around lines 178 - 195, The code currently returns the
sole enabledSAMLConfigs[0].IdpConfigurationId without honoring idpConfigName;
change the logic in the selection block so that when len(enabledSAMLConfigs) ==
1 you still check idpConfigName: if idpConfigName is empty, return
enabledSAMLConfigs[0].IdpConfigurationId, otherwise call
findIDPByName(enabledSAMLConfigs, idpConfigName) and return an InvalidArgument
error (use uhttp.WrapErrors with buildMultipleIDPError) if the name doesn't
match, otherwise return the matched selectedConfig.IdpConfigurationId; this
preserves current behavior for empty names but surfaces typos/misconfigurations
when a name is provided.

@aldevv aldevv requested review from a team and btipling January 23, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants