Skip to content

Conversation

@adambenhassen
Copy link
Collaborator

@adambenhassen adambenhassen commented Dec 15, 2025

Closes #7239

Description

Adds filtering capability to the organization access tokens page and tracks who created each token.

Features

  • Filter tokens by scope (organization, project, personal), multipe scopes can be selected at the same time
  • Filter personal tokens by user
  • Display "Created By" column showing who created each token, when available
Screenshot 2025-12-15 at 16 14 03

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @adambenhassen, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the management of access tokens by introducing robust filtering options and improving auditability. Users can now easily locate specific tokens by filtering based on their scope (organization, project, or personal) and, for personal tokens, by the creator. The addition of a 'Created By' field provides crucial context for each token, making it easier to track and manage access within the organization.

Highlights

  • Access Token Filtering: Introduced filtering capabilities for access tokens, allowing users to filter by scope (Organization, Project, Personal) and by the user who created personal tokens.
  • Creator Tracking: Added a 'Created By' column to the access token display, showing which user generated each token. This involved adding a new created_by_user_id column to the database and updating GraphQL types and resolvers.
  • GraphQL API Enhancements: The GraphQL API now supports filtering access tokens via new scopes and userId arguments in the allAccessTokens query, and includes createdBy information for all access token types.
  • User Interface Updates: The organization access tokens page in the web application has been updated with new dropdown filters for scope and owner, and a 'Created By' column in the access tokens table.
  • Integration Tests: Comprehensive integration tests have been added to validate the new filtering logic for various scope combinations and user IDs, as well as to ensure the createdBy information is correctly returned.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 15, 2025

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
hive 8.14.0-alpha-20251215162720-f6ff82a3c9e9a3e7e39c6cc13eb8d89e657948df npm ↗︎ unpkg ↗︎

@github-actions
Copy link
Contributor

github-actions bot commented Dec 15, 2025

📚 Storybook Deployment

The latest changes are available as preview in: https://pr-7430.hive-storybook.pages.dev

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces filtering for access tokens by scope and user, and adds tracking for token creators. The changes are well-implemented across the backend, database, and frontend, and include a comprehensive set of integration tests. My review includes suggestions to reduce code duplication in tests, align with backend architectural guidelines, and a minor code simplification.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 15, 2025

💻 Website Preview

The latest changes are available as preview in: https://pr-7430.hive-landing-page.pages.dev

@github-actions
Copy link
Contributor

github-actions bot commented Dec 15, 2025

🐋 This PR was built and pushed to the following Docker images:

Targets: build

Platforms: linux/amd64

Image Tag: f6ff82a3c9e9a3e7e39c6cc13eb8d89e657948df

Copy link
Collaborator

Choose a reason for hiding this comment

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

Should the AccessToken interface have createdBy added as well?

/**
* Whether only access tokens on the organization scope should be included in the result.
* @deprecated Use `filter: { scopes: ['ORGANIZATION'] }` instead.
*/
Copy link
Collaborator

Choose a reason for hiding this comment

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

nice callout


const AccessTokensTable_MoreAccessTokensQuery = graphql(`
query AccessTokensTable_MoreAccessTokensQuery($organizationSlug: String!, $after: String) {
query AccessTokensTable_MoreAccessTokensQuery(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this was broken even before this change, but loading more doesn't work. I tested locally w/11 tokens.

description: args.description,
assignedResources,
permissions,
createdByUserId: actor.type === 'user' ? actor.user.id : null,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This may be outside the scope of this ticket, but here's something to consider:

I keep encountering these situations where we rely on the author's ID to show who created something.

I wonder if the token were created using another token, should we store that token's "createdByUserId" here? Or maybe in the future we store a "createdByToken"?
For personal access tokens, I feel like storing the userId is appropriate, but for org or project scoped tokens it makes less sense.

checked={validatedScopeFilter.includes(scope)}
onCheckedChange={() => handleScopeToggle(scope)}
>
{scopeLabels[scope]}
Copy link
Collaborator

Choose a reason for hiding this comment

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

For multi-selects I think it's important to keep the menu visible on click to allow users to select multiple without having to reopen.

There's a similar filter for the status on schema proposals for reference. In terms of style -- I'm find with either design for the menu/checkboxes, but I think we should be consistent between pages. So perhaps someone else can weigh in on the style.

</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuLabel>Filter by scope</DropdownMenuLabel>
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think these labels are redundant with the button text. My preference is to remove the label.

</DropdownMenuContent>
</DropdownMenu>

{/* User Filter Dropdown (only show if there are users) */}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I was exploring using a user filter for proposals as well -- you should be able to use it for this menu if you'd like. It includes search functionality so that pagination is less of an issue packages/web/app/src/components/target/proposals/user-filter.tsx

I had intended it to also allow multiple users to be selected though, so your userId filter would need to be an array or this behavior would need tweaked.

If you want to keep this component, then please move it to its own component file to keep this page a bit more concise.

export function AccessTokensSubPage(props: AccessTokensSubPageProps): React.ReactNode {
// URL-based filter state
const [scopeFilter, setScopeFilter] = useSearchParamsFilter<string[]>('scope', []);
const [userFilter, setUserFilter] = useSearchParamsFilter<string>('user', '');
Copy link
Collaborator

Choose a reason for hiding this comment

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

I like that you're tracking filters in the url.

<Table.TableCell>
{'createdBy' in edge.node && edge.node.createdBy ? (
<span className="text-sm">
{edge.node.createdBy.displayName || edge.node.createdBy.email}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we fallback to the fullName before showing just the email?

};

const activeFilterCount =
(validatedScopeFilter.length > 0 && validatedScopeFilter.length < 3 ? 1 : 0) +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Minor: I like that you show the filter count but it's a little odd when selecting the 3rd and the count disappears. I think I'd prefer if the count says 3 even though the filter itself is equivalent to not having a selection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

access token: filter displaced access tokens by scope and user

2 participants