Skip to content

CXH-356 Add dashboard#25

Merged
aldevv merged 8 commits intomainfrom
add_dashboard
Feb 3, 2026
Merged

CXH-356 Add dashboard#25
aldevv merged 8 commits intomainfrom
add_dashboard

Conversation

@aldevv
Copy link
Contributor

@aldevv aldevv commented Jan 29, 2026

Summary by CodeRabbit

  • New Features

    • Manage Tableau views as first-class resources: listing, entitlements, grants, and revocations.
    • Client API adds view-level permission endpoints and related capability types.
    • Views are included in the site hierarchy for correct site-scoped access.
  • Bug Fixes

    • Group processing now skips server-level administrators when determining site-scoped group membership.

@aldevv aldevv requested a review from a team January 29, 2026 17:18
@linear
Copy link

linear bot commented Jan 29, 2026

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

Adds Tableau "View" resource support: new connector resource type, client APIs and models for views and view permissions, site annotations updated to include views, and group logic updated to skip ServerAdministrator users when computing grants.

Changes

Cohort / File(s) Summary
Tableau API Models
pkg/tableau/models.go
Add View, GranteeCapabilities, UserRef, GroupRef, Capabilities, and Capability types for view and permission payloads.
Tableau API Client
pkg/tableau/client.go
Add view-related methods (GetViews, GetPaginatedViews, GetViewPermissions, `Add/Delete View (User
Connector View Implementation
pkg/connector/view.go
New view resource type: capability constants/map, viewResourceType with methods ResourceType, List, Entitlements, Grants, Grant, Revoke, viewBuilder, and entitlement-id parsing helper.
Connector Registration & Site Annotations
pkg/connector/connector.go, pkg/connector/site.go
Register viewBuilder in connector syncers and add resourceTypeView to Site child resources; lower unknown-role log level to debug.
Group Grants Filtering
pkg/connector/group.go
Introduce siteRoleServerAdmin constant and skip users with SiteRole == "ServerAdministrator" when computing group grants; convert some warnings to debug logs.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    rect rgba(200,200,255,0.5)
    participant Client as Baton Client
    end
    rect rgba(200,255,200,0.5)
    participant Connector as Baton Connector
    end
    rect rgba(255,200,200,0.5)
    participant TableauClient as Tableau Client
    end
    rect rgba(255,255,200,0.5)
    participant API as Tableau API
    end

    Client->>Connector: List views / Get entitlements / Grant / Revoke
    Connector->>TableauClient: GetPaginatedViews() / GetViewPermissions(viewID) / Add/Delete View Permission
    TableauClient->>API: GET /sites/{siteId}/views (paginated)
    TableauClient->>API: GET /views/{viewId}/permissions
    TableauClient->>API: PUT/DELETE /views/{viewId}/permissions (user|group)
    API-->>TableauClient: Views pages / GranteeCapabilities / Success
    TableauClient-->>Connector: Views / Capabilities / Result
    Connector->>Client: Resources / Entitlements / Operation outcome
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • FeliLucero1
  • btipling

Poem

🐇 I hopped through views both near and far,
New capabilities bright as a star,
Grants and revokes in tidy queues,
Skipping admins, minding the clues,
A cheerful rabbit says, "Well done!" 🎉

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Add dashboard' is misleading; the changeset primarily implements Tableau view resource support, not dashboard functionality. Update the title to accurately reflect the main change, such as 'Add Tableau view resource connector support' or 'Implement view resource integration with permissions'.
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 (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add_dashboard

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: 2

🤖 Fix all issues with AI agents
In `@pkg/connector/group.go`:
- Around line 18-21: Run goimports to fix import formatting and lint errors in
the file containing the constants memberEntitlement and siteRoleServerAdmin;
re-run goimports (or goimports -w .) to rewrite the file with properly
grouped/ordered imports and formatted code, then save and re-run CI to ensure
the verify step passes.
- Around line 111-121: The debug log in the for loop over users logs user.Email
(PII); remove or redact that field — update the logging call in the loop (for _,
user := range users) that uses l.Debug to omit zap.String("user_email",
user.Email) (or replace it with a non-PII placeholder) and keep non-sensitive
identifiers like "group_id" and "user_id" only; ensure the change is applied
where server admin users are skipped (the skip branch referencing
siteRoleServerAdmin and variables groupId, user.ID, user.Email).

@aldevv aldevv requested a review from a team January 29, 2026 19:09
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/view.go`:
- Around line 106-159: The Grants method on viewResourceType may emit grants for
unknown capability names; update Grants to filter capability.Name against the
known viewCapabilities set before creating grants. Specifically, in Grants
(function viewResourceType.Grants) build or reuse a lookup (e.g.,
map[string]struct{} from viewCapabilities) and skip any capability whose Name is
not present; apply this check before the user grant creation block (where
rs.NewResourceID/resourceTypeUser is used) and before the group grant creation
block (where resourceTypeGroup and grant.WithAnnotation are used) so only known
entitlement names produce Grant objects.
🧹 Nitpick comments (1)
pkg/connector/view.go (1)

66-87: Consider honoring pagination tokens for large sites.

List currently ignores token and always loads all views, which can be costly for large tenants. Consider using the token to page through views incrementally rather than fetching everything at once.

Comment on lines +106 to +159
func (v *viewResourceType) Grants(ctx context.Context, resource *v2.Resource, token *pagination.Token) ([]*v2.Grant, string, annotations.Annotations, error) {
l := ctxzap.Extract(ctx)
var rv []*v2.Grant

viewID := resource.Id.Resource

permissions, err := v.client.GetViewPermissions(ctx, viewID)
if err != nil {
l.Debug(
"baton-tableau: failed to get view permissions, skipping grants for this view",
zap.String("view_id", viewID),
zap.String("view_name", resource.DisplayName),
zap.Error(err),
)
return rv, "", nil, nil
}

for _, grantee := range permissions {
for _, capability := range grantee.Capabilities.Capability {
if capability.Mode != "Allow" {
continue
}

if grantee.User != nil {
principalID, err := rs.NewResourceID(resourceTypeUser, grantee.User.ID)
if err != nil {
return nil, "", nil, fmt.Errorf("tableau-connector: failed to create user resource ID: %w", err)
}
g := grant.NewGrant(resource, capability.Name, principalID)
rv = append(rv, g)
}

if grantee.Group != nil {
groupID := grantee.Group.ID
principalID, err := rs.NewResourceID(resourceTypeGroup, groupID)
if err != nil {
return nil, "", nil, fmt.Errorf("tableau-connector: failed to create group resource ID: %w", err)
}
g := grant.NewGrant(
resource,
capability.Name,
principalID,
grant.WithAnnotation(&v2.GrantExpandable{
EntitlementIds: []string{fmt.Sprintf("group:%s:%s", groupID, memberEntitlement)},
Shallow: true,
}),
)
rv = append(rv, g)
}
}
}

return rv, "", nil, 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

Filter grants to known capability entitlements.

If Tableau returns a capability not present in viewCapabilities, this will emit grants for entitlements that don’t exist, which can break reconciliation. Consider filtering to known capabilities before creating grants.

✅ Suggested filter
 for _, grantee := range permissions {
     for _, capability := range grantee.Capabilities.Capability {
+        if _, ok := viewCapabilities[capability.Name]; !ok {
+            continue
+        }
         if capability.Mode != "Allow" {
             continue
         }
🤖 Prompt for AI Agents
In `@pkg/connector/view.go` around lines 106 - 159, The Grants method on
viewResourceType may emit grants for unknown capability names; update Grants to
filter capability.Name against the known viewCapabilities set before creating
grants. Specifically, in Grants (function viewResourceType.Grants) build or
reuse a lookup (e.g., map[string]struct{} from viewCapabilities) and skip any
capability whose Name is not present; apply this check before the user grant
creation block (where rs.NewResourceID/resourceTypeUser is used) and before the
group grant creation block (where resourceTypeGroup and grant.WithAnnotation are
used) so only known entitlement names produce Grant objects.

@aldevv aldevv requested a review from btipling February 3, 2026 17:23
return rv, "", nil, nil
}

func (v *viewResourceType) Entitlements(_ context.Context, resource *v2.Resource, _ *pagination.Token) ([]*v2.Entitlement, string, annotations.Annotations, error) {
Copy link

Choose a reason for hiding this comment

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

Should be static entitlements?

case resourceTypeGroup.Id:
err = v.client.DeleteViewGroupPermission(ctx, viewID, principalID, capabilityName, "Allow")
default:
l.Warn(
Copy link

Choose a reason for hiding this comment

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

Warn -> Debug, always. Please leave a comment in the code to explain the warn if you think there's a reason to use warn.

principalID,
grant.WithAnnotation(&v2.GrantExpandable{
EntitlementIds: []string{fmt.Sprintf("group:%s:%s", groupID, memberEntitlement)},
Shallow: true,
Copy link

Choose a reason for hiding this comment

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

I noticed I think that views can also be assignable to Group Sets, which we don't support as a resource type, but maybe we should?

https://help.tableau.com/current/online/en-us/group_sets.htm

For example, you might restrict access to different workbook views based on a user’s regional group affiliation. Suppose you have users who are, contractors, contractor managers, full time employees, and full time managers accessing these workbook views.

Groups that have default permissions to view the workbook: All, North, South, East, West, Full Time, and Managers.

For the North Region Detailed view:
Permissions are based on group set: North Region
Groups in the group set: Full Time, North
Outcome: Only full time employees and full time managers in the north can see the data in the North Region Detailed view.

For the All Region Detailed view:
Group set is called Managers
Groups in the group set: All, Managers
Outcome: Only contractor managers and full time managers can see the data in the All Region Detailed view.

Copy link

Choose a reason for hiding this comment

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

I am unsure about this.

@aldevv aldevv merged commit b91e81a into main Feb 3, 2026
4 checks passed
@aldevv aldevv deleted the add_dashboard branch February 3, 2026 21:38
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.

3 participants