Added scopes page

This commit is contained in:
Matt Aitken
2023-06-12 15:59:34 +01:00
parent 49a510aaf9
commit d55fe2d100
5 changed files with 129 additions and 14 deletions
@@ -0,0 +1,70 @@
import { User } from ".prisma/client";
import { PrismaClient, prisma } from "~/db.server";
import { env } from "~/env.server";
import { Organization } from "~/models/organization.server";
import { Project } from "~/models/project.server";
import { apiAuthenticationRepository } from "~/services/externalApis/apiAuthenticationRepository.server";
import {
ConnectionMetadataSchema,
OAuthClientSchema,
} from "~/services/externalApis/types";
import { getSecretStore } from "~/services/secrets/secretStore.server";
export class IntegrationClientScopesPresenter {
#prismaClient: PrismaClient;
constructor(prismaClient: PrismaClient = prisma) {
this.#prismaClient = prismaClient;
}
public async call({
userId,
organizationSlug,
projectSlug,
clientSlug,
}: {
userId: User["id"];
organizationSlug: Organization["slug"];
projectSlug: Project["slug"];
clientSlug: string;
}) {
const client = await this.#prismaClient.apiConnectionClient.findFirst({
select: {
integrationIdentifier: true,
integrationAuthMethod: true,
scopes: true,
},
where: {
organization: {
slug: organizationSlug,
members: {
some: {
userId,
},
},
},
slug: clientSlug,
},
});
if (!client) {
throw new Error("Client not found");
}
const { integration, authMethod } =
apiAuthenticationRepository.getIntegrationAndAuthMethod(client);
return {
scopes: client.scopes.map((s) => {
const matchingScope = authMethod.scopes.find(
(scope) => scope.name === s
);
return {
name: s,
description: matchingScope?.description,
};
}),
};
}
}
@@ -1,28 +1,22 @@
import { LoaderArgs } from "@remix-run/server-runtime";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { connectionType } from "~/components/integrations/connectionType";
import { DateTime } from "~/components/primitives/DateTime";
import { LabelValueStack } from "~/components/primitives/LabelValueStack";
import { NamedIcon } from "~/components/primitives/NamedIcon";
import { Paragraph } from "~/components/primitives/Paragraph";
import {
Table,
TableBlankRow,
TableBody,
TableCell,
TableCellChevron,
TableHeader,
TableHeaderCell,
TableRow,
} from "~/components/primitives/Table";
import { SimpleTooltip } from "~/components/primitives/Tooltip";
import { runStatusTitle } from "~/components/runs/RunStatuses";
import { useIntegrationClient } from "~/hooks/useIntegrationClient";
import { useProject } from "~/hooks/useProject";
import { IntegrationClientConnectionsPresenter } from "~/presenters/IntegrationClientConnectionsPresenter.server";
import { requireUserId } from "~/services/session.server";
import { formatDateTime } from "~/utils";
import { IntegrationClientParamSchema, jobPath } from "~/utils/pathBuilder";
import { IntegrationClientParamSchema } from "~/utils/pathBuilder";
export const loader = async ({ request, params }: LoaderArgs) => {
const userId = await requireUserId(request);
@@ -0,0 +1,57 @@
import { LoaderArgs } from "@remix-run/server-runtime";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { connectionType } from "~/components/integrations/connectionType";
import { DateTime } from "~/components/primitives/DateTime";
import { LabelValueStack } from "~/components/primitives/LabelValueStack";
import { NamedIcon } from "~/components/primitives/NamedIcon";
import { Paragraph } from "~/components/primitives/Paragraph";
import {
Table,
TableBlankRow,
TableBody,
TableCell,
TableCellChevron,
TableHeader,
TableHeaderCell,
TableRow,
} from "~/components/primitives/Table";
import { SimpleTooltip } from "~/components/primitives/Tooltip";
import { runStatusTitle } from "~/components/runs/RunStatuses";
import { useIntegrationClient } from "~/hooks/useIntegrationClient";
import { useProject } from "~/hooks/useProject";
import { IntegrationClientConnectionsPresenter } from "~/presenters/IntegrationClientConnectionsPresenter.server";
import { IntegrationClientScopesPresenter } from "~/presenters/IntegrationClientScopesPresenter.server";
import { requireUserId } from "~/services/session.server";
import { formatDateTime } from "~/utils";
import { IntegrationClientParamSchema, jobPath } from "~/utils/pathBuilder";
export const loader = async ({ request, params }: LoaderArgs) => {
const userId = await requireUserId(request);
const { organizationSlug, projectParam, clientParam } =
IntegrationClientParamSchema.parse(params);
const presenter = new IntegrationClientScopesPresenter();
const { scopes } = await presenter.call({
userId: userId,
organizationSlug,
projectSlug: projectParam,
clientSlug: clientParam,
});
return typedjson({ scopes });
};
export default function Page() {
const { scopes } = useTypedLoaderData<typeof loader>();
return (
<ul className="flex max-w-md flex-col gap-4 divide-y divide-slate-800">
{scopes.map((scope) => (
<li key={scope.name} className="flex flex-col gap-1 pt-4 first:pt-0">
<Paragraph className="font-mono text-bright">{scope.name}</Paragraph>
<Paragraph variant="small">{scope.description}</Paragraph>
</li>
))}
</ul>
);
}
@@ -2,13 +2,9 @@ import { Outlet } from "@remix-run/react";
import { LoaderArgs } from "@remix-run/server-runtime";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { ClipboardField } from "~/components/ClipboardField";
import { CodeBlock } from "~/components/code/CodeBlock";
import { InlineCode } from "~/components/code/InlineCode";
import { connectionType } from "~/components/integrations/connectionType";
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
import { Button } from "~/components/primitives/Buttons";
import {
PageButtons,
PageHeader,
PageInfoGroup,
PageInfoProperty,
@@ -17,7 +13,6 @@ import {
PageTitle,
PageTitleRow,
} from "~/components/primitives/PageHeader";
import { Paragraph } from "~/components/primitives/Paragraph";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { IntegrationClientPresenter } from "~/presenters/IntegrationClientPresenter.server";
@@ -1,7 +1,6 @@
import { Outlet } from "@remix-run/react";
import type { LoaderArgs } from "@remix-run/server-runtime";
import { typedjson } from "remix-typedjson";
import invariant from "tiny-invariant";
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
import { LinkButton } from "~/components/primitives/Buttons";
import { NamedIcon } from "~/components/primitives/NamedIcon";
@@ -19,7 +18,7 @@ import { Paragraph } from "~/components/primitives/Paragraph";
import { useJob } from "~/hooks/useJob";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { useOptionalRun, useRun } from "~/hooks/useRun";
import { useOptionalRun } from "~/hooks/useRun";
import { findJobByParams } from "~/models/job.server";
import { requireUserId } from "~/services/session.server";
import { Handle } from "~/utils/handle";