Skip to content

Commit

Permalink
Builders have access to admin list on Connections page (#6240)
Browse files Browse the repository at this point in the history
* Builders have access to admin list on Connections page

* Do not reuse MembersList, we want a simpler design

* clean
  • Loading branch information
PopDaph authored and albandum committed Aug 28, 2024
1 parent 8efbd29 commit 1e3cc71
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 19 deletions.
15 changes: 15 additions & 0 deletions front/lib/swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,21 @@ export function useMembers(owner: WorkspaceType) {
};
}

export function useAdmins(owner: WorkspaceType) {
const membersFetcher: Fetcher<GetMembersResponseBody> = fetcher;
const { data, error, mutate } = useSWRWithDefaults(
`/api/w/${owner.sId}/members?role=admin`,
membersFetcher
);

return {
admins: useMemo(() => (data ? data.members : []), [data]),
isAdminsLoading: !error && !data,
iAdminsError: error,
mutateMembers: mutate,
};
}

export function useWorkspaceInvitations(owner: WorkspaceType) {
const workspaceInvitationsFetcher: Fetcher<GetWorkspaceInvitationsResponseBody> =
fetcher;
Expand Down
8 changes: 4 additions & 4 deletions front/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@amplitude/analytics-browser": "^2.5.2",
"@amplitude/analytics-node": "^1.3.5",
"@auth0/nextjs-auth0": "^3.5.0",
"@dust-tt/sparkle": "^0.2.190",
"@dust-tt/sparkle": "^0.2.191",
"@dust-tt/types": "file:../types",
"@emoji-mart/data": "^1.1.2",
"@emoji-mart/react": "^1.1.1",
Expand Down
28 changes: 17 additions & 11 deletions front/pages/api/w/[wId]/members/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@ async function handler(
res: NextApiResponse<WithAPIErrorResponse<GetMembersResponseBody>>,
auth: Authenticator
): Promise<void> {
if (!auth.isAdmin()) {
return apiError(req, res, {
status_code: 403,
api_error: {
type: "workspace_auth_error",
message:
"Only users that are `admins` for the current workspace can see memberships or modify it.",
},
});
}

switch (req.method) {
case "GET":
if (auth.isBuilder() && req.query.role && req.query.role === "admin") {
const members = await getMembers(auth, { roles: ["admin"] });
res.status(200).json({ members });
return;
}

if (!auth.isAdmin()) {
return apiError(req, res, {
status_code: 403,
api_error: {
type: "workspace_auth_error",
message:
"Only users that are `admins` for the current workspace can see memberships or modify it.",
},
});
}

const members = await getMembers(auth);

res.status(200).json({ members });
Expand Down
73 changes: 70 additions & 3 deletions front/pages/w/[wId]/builder/data-sources/managed.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
Avatar,
BookOpenIcon,
Button,
Chip,
CloudArrowLeftRightIcon,
Cog6ToothIcon,
ContentMessage,
ContextItem,
Hoverable,
InformationCircleIcon,
Modal,
Page,
Expand Down Expand Up @@ -36,6 +38,7 @@ import { buildConnectionId } from "@app/lib/connector_connection_id";
import { CONNECTOR_CONFIGURATIONS } from "@app/lib/connector_providers";
import { githubAuth } from "@app/lib/github_auth";
import { withDefaultUserAuthRequirements } from "@app/lib/iam/session";
import { useAdmins } from "@app/lib/swr";
import { timeAgoFrom } from "@app/lib/utils";
import logger from "@app/logger/logger";
import type { PostManagedDataSourceRequestBody } from "@app/pages/api/w/[wId]/data_sources/managed";
Expand Down Expand Up @@ -404,6 +407,9 @@ export default function DataSourcesView({
const [showConfirmConnection, setShowConfirmConnection] =
useState<DataSourceIntegration | null>(null);

const [showAdminsModal, setShowAdminsModal] = useState(false);
const { admins, isAdminsLoading } = useAdmins(owner);

const handleEnableManagedDataSource = async (
provider: ConnectorProvider,
suffix: string | null
Expand Down Expand Up @@ -520,6 +526,60 @@ export default function DataSourcesView({
current: "data_sources_managed",
})}
>
{!isAdmin && (
<Modal
isOpen={showAdminsModal}
title="Administrators"
onClose={() => setShowAdminsModal(false)}
hasChanged={false}
variant="side-sm"
>
<div className="flex flex-col gap-5 pt-6 text-sm text-element-700">
<Page.SectionHeader
title="Administrators"
description={`${owner.name} has the following administrators:`}
/>
{isAdminsLoading ? (
<div className="flex animate-pulse items-center justify-center gap-3 border-t border-structure-200 bg-structure-50 py-2 text-xs sm:text-sm">
<div className="hidden sm:block">
<Avatar size="xs" />
</div>
<div className="flex grow flex-col gap-1 sm:flex-row sm:gap-3">
<div className="font-medium text-element-900">Loading...</div>
<div className="grow font-normal text-element-700"></div>
</div>
</div>
) : (
<div className="s-w-full">
{admins.map((admin) => {
return (
<div
key={`member-${admin.id}`}
className="flex items-center justify-center gap-3 border-t border-structure-200 p-2 text-xs sm:text-sm"
>
<div className="hidden sm:block">
<Avatar
visual={admin.image}
name={admin.fullName}
size="sm"
/>
</div>
<div className="flex grow flex-col gap-1 sm:flex-row sm:gap-3">
<div className="font-medium text-element-900">
{admin.fullName}
</div>
<div className="grow font-normal text-element-700">
{admin.email}
</div>
</div>
</div>
);
})}
</div>
)}
</div>
</Modal>
)}
{showConfirmConnection && (
<ConfirmationModal
dataSource={showConfirmConnection}
Expand All @@ -539,9 +599,16 @@ export default function DataSourcesView({
icon={CloudArrowLeftRightIcon}
description="Manage connections to your products and the real-time data feeds Dust has access to."
/>
{owner.role !== "admin" && (
<ContentMessage title="Roles">
Only Admins can activate and manage Connections.
{!isAdmin && (
<ContentMessage title="How are connections managed?">
<b>Workspace administrators</b> control access to connections for
all members.{" "}
<Hoverable
variant="primary"
onClick={() => setShowAdminsModal(true)}
>
View the list of administrators here.
</Hoverable>
</ContentMessage>
)}
<ContextItem.List>
Expand Down

0 comments on commit 1e3cc71

Please sign in to comment.