Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove usage of scopes for target access tokens #6328

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import { AlertTriangleIcon, TrashIcon } from '@/components/ui/icon';
import { SubPageLayout, SubPageLayoutHeader } from '@/components/ui/page-content-layout';
import { Input, Modal, Table, Tag, TBody, Td, TimeAgo, Tr } from '@/components/v2';
import { InlineCode } from '@/components/v2/inline-code';
import { FragmentType, graphql, useFragment } from '@/gql';
import { TargetAccessScope } from '@/gql/graphql';
import { canAccessTarget } from '@/lib/access/target';
import { graphql, useFragment } from '@/gql';
import { Link, useRouter } from '@tanstack/react-router';

const CDNAccessTokeRowFragment = graphql(`
Expand Down Expand Up @@ -317,12 +315,6 @@ const CDNAccessTokensQuery = graphql(`
}
`);

const CDNAccessTokens_MeFragment = graphql(`
fragment CDNAccessTokens_MeFragment on Member {
...CanAccessTarget_MemberFragment
}
`);

const CDNSearchParams = z.discriminatedUnion('cdn', [
z.object({
cdn: z.literal('create').optional(),
Expand All @@ -334,13 +326,10 @@ const CDNSearchParams = z.discriminatedUnion('cdn', [
]);

export function CDNAccessTokens(props: {
me: FragmentType<typeof CDNAccessTokens_MeFragment>;
organizationSlug: string;
projectSlug: string;
targetSlug: string;
}): React.ReactElement {
const me = useFragment(CDNAccessTokens_MeFragment, props.me);

const [endCursors, setEndCursors] = useState<Array<string>>([]);
const router = useRouter();
const searchParamsResult = CDNSearchParams.safeParse(router.latestLocation.search);
Expand Down Expand Up @@ -373,8 +362,6 @@ export function CDNAccessTokens(props: {
requestPolicy: 'cache-and-network',
});

const canManage = canAccessTarget(TargetAccessScope.Settings, me);

return (
<SubPageLayout>
<SubPageLayoutHeader
Expand All @@ -396,20 +383,18 @@ export function CDNAccessTokens(props: {
</>
}
/>
{canManage && (
<div className="my-3.5 flex justify-between">
<Button asChild>
<Link
search={{
page: 'cdn',
cdn: 'create',
}}
>
Create new CDN token
</Link>
</Button>
</div>
)}
<div className="my-3.5 flex justify-between">
n1ru4l marked this conversation as resolved.
Show resolved Hide resolved
<Button asChild>
<Link
search={{
page: 'cdn',
cdn: 'create',
}}
>
Create new CDN token
</Link>
</Button>
</div>
<Table>
<TBody>
{target?.data?.target?.cdnAccessTokens.edges?.map(edge => {
Expand All @@ -425,23 +410,21 @@ export function CDNAccessTokens(props: {
created <TimeAgo date={node.createdAt} />
</Td>
<Td align="right">
{canManage ? (
<Button
className="hover:text-red-500"
variant="ghost"
onClick={() => {
void router.navigate({
search: {
page: 'cdn',
cdn: 'delete',
id: node.id,
},
});
}}
>
<TrashIcon />
</Button>
) : null}
<Button
className="hover:text-red-500"
variant="ghost"
onClick={() => {
void router.navigate({
search: {
page: 'cdn',
cdn: 'delete',
id: node.id,
},
});
}}
>
<TrashIcon />
</Button>
</Td>
</Tr>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react';
import { useForm, UseFormReturn } from 'react-hook-form';
import { AnyVariables, useMutation, UseMutationState, useQuery } from 'urql';
import { AnyVariables, useMutation, UseMutationState } from 'urql';
import { z } from 'zod';
import { Tag } from '@/components//v2/tag';
import { PermissionScopeItem, usePermissionsManager } from '@/components/organization/Permissions';
import { PermissionScopeItem } from '@/components/organization/Permissions';
import { Button } from '@/components/ui/button';
import {
Dialog,
Expand All @@ -18,7 +18,7 @@ import { Input } from '@/components/ui/input';
import { InputCopy } from '@/components/ui/input-copy';
import { useToast } from '@/components/ui/use-toast';
import { Accordion } from '@/components/v2/accordion';
import { FragmentType, graphql, useFragment } from '@/gql';
import { graphql } from '@/gql';
import { TargetAccessScope } from '@/gql/graphql';
import { RegistryAccessScope } from '@/lib/access/common';
import { zodResolver } from '@hookform/resolvers/zod';
Expand Down Expand Up @@ -48,16 +48,6 @@ export const CreateAccessToken_CreateTokenMutation = graphql(`
}
`);

const CreateAccessTokenModalQuery = graphql(`
query CreateAccessTokenModalQuery($organizationSlug: String!) {
organization(selector: { organizationSlug: $organizationSlug }) {
organization {
...CreateAccessTokenModalContent_OrganizationFragment
}
}
}
`);

export function CreateAccessTokenModal(props: {
isOpen: boolean;
toggleModalOpen: () => void;
Expand All @@ -66,52 +56,19 @@ export function CreateAccessTokenModal(props: {
targetSlug: string;
}) {
const { isOpen, toggleModalOpen } = props;
const [organizationQuery] = useQuery({
query: CreateAccessTokenModalQuery,
variables: {
organizationSlug: props.organizationSlug,
},
});

const organization = organizationQuery.data?.organization?.organization;

return (
<Dialog open={isOpen} onOpenChange={toggleModalOpen}>
{organization ? (
<ModalContent
organization={organization}
organizationSlug={props.organizationSlug}
projectSlug={props.projectSlug}
targetSlug={props.targetSlug}
toggleModalOpen={toggleModalOpen}
/>
) : (
<DialogContent className="container w-4/5 max-w-[600px] md:w-3/5">
<DialogHeader>
<DialogTitle>Organization not found</DialogTitle>
<DialogDescription>
The organization you are trying to access does not exist.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button onClick={toggleModalOpen}>Ok, got it!</Button>
</DialogFooter>
</DialogContent>
)}
<ModalContent
organizationSlug={props.organizationSlug}
projectSlug={props.projectSlug}
targetSlug={props.targetSlug}
toggleModalOpen={toggleModalOpen}
/>
</Dialog>
);
}

const CreateAccessTokenModalContent_OrganizationFragment = graphql(`
fragment CreateAccessTokenModalContent_OrganizationFragment on Organization {
id
...UsePermissionManager_OrganizationFragment
me {
...UsePermissionManager_MemberFragment
}
}
`);

function getFinalTargetAccessScopes(
selectedScope: 'no-access' | TargetAccessScope,
): Array<TargetAccessScope> {
Expand Down Expand Up @@ -142,26 +99,14 @@ const createRegistryTokenFormSchema = z.object({
});

export function ModalContent(props: {
organization: FragmentType<typeof CreateAccessTokenModalContent_OrganizationFragment>;
organizationSlug: string;
projectSlug: string;
targetSlug: string;
toggleModalOpen: () => void;
}) {
const { toast } = useToast();
const organization = useFragment(
CreateAccessTokenModalContent_OrganizationFragment,
props.organization,
);
const [selectedScope, setSelectedScope] = useState<'no-access' | TargetAccessScope>('no-access');

const manager = usePermissionsManager({
onSuccess() {},
organization,
member: organization.me,
passMemberScopes: false,
});

const form = useForm<z.infer<typeof createRegistryTokenFormSchema>>({
mode: 'onChange',
resolver: zodResolver(createRegistryTokenFormSchema),
Expand Down Expand Up @@ -206,7 +151,6 @@ export function ModalContent(props: {
return (
<GenerateTokenContent
form={form}
manager={manager}
noPermissionsSelected={noPermissionsSelected}
onSubmit={onSubmit}
selectedScope={selectedScope} // Ensure selectedScope is passed correctly
Expand Down Expand Up @@ -247,7 +191,6 @@ export function CreatedTokenContent(props: {
export function GenerateTokenContent(props: {
form: UseFormReturn<z.infer<typeof createRegistryTokenFormSchema>>;
onSubmit: (values: z.infer<typeof createRegistryTokenFormSchema>) => void;
manager: ReturnType<typeof usePermissionsManager>;
setSelectedScope: (scope: 'no-access' | TargetAccessScope) => void;
selectedScope: 'no-access' | TargetAccessScope;
toggleModalOpen: () => void;
Expand Down Expand Up @@ -293,11 +236,8 @@ export function GenerateTokenContent(props: {
dataCy="registry-access-scope"
key={props.selectedScope}
scope={RegistryAccessScope}
canManageScope={
props.manager.canAccessTarget(RegistryAccessScope.mapping['read-only']) ||
props.manager.canAccessTarget(RegistryAccessScope.mapping['read-write'])
}
checkAccess={props.manager.canAccessTarget}
canManageScope
checkAccess={() => true}
onChange={value => {
if (value === 'no-access') {
props.setSelectedScope('no-access');
Expand Down
5 changes: 0 additions & 5 deletions packages/web/app/src/pages/target-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,6 @@ const TargetSettingsPage_OrganizationFragment = graphql(`
me {
...CanAccessTarget_MemberFragment
...RegistryAccessTokens_MeFragment
...CDNAccessTokens_MeFragment
}
}
`);
Expand Down Expand Up @@ -1072,9 +1071,6 @@ const TargetSettingsPageQuery = graphql(`
id
slug
...TargetSettingsPage_OrganizationFragment
me {
...CDNAccessTokens_MeFragment
}
}
}
project(selector: { organizationSlug: $organizationSlug, projectSlug: $projectSlug }) {
Expand Down Expand Up @@ -1279,7 +1275,6 @@ function TargetSettingsContent(props: {
) : null}
{resolvedPage.key === 'cdn' ? (
<CDNAccessTokens
me={organizationForSettings.me}
organizationSlug={props.organizationSlug}
projectSlug={props.projectSlug}
targetSlug={props.targetSlug}
Expand Down
Loading
Loading