mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
fix: handle group memberships in secret versions history and fix secret versions query to always return all versions
This commit is contained in:
@@ -109,6 +109,7 @@ export type SecretVersions = {
|
||||
actorType?: string | null;
|
||||
name?: string | null;
|
||||
membershipId?: string | null;
|
||||
groupId?: string | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo } from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import {
|
||||
faArrowDown,
|
||||
faArrowUp,
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
faSearch
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
@@ -48,6 +49,7 @@ enum GroupMembersOrderBy {
|
||||
}
|
||||
|
||||
export const GroupMembersTable = ({ groupMembership }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
search,
|
||||
setSearch,
|
||||
@@ -62,6 +64,21 @@ export const GroupMembersTable = ({ groupMembership }: Props) => {
|
||||
initPerPage: getUserTablePreference("projectGroupMembersTable", PreferenceKey.PerPage, 20)
|
||||
});
|
||||
|
||||
// this handles links from secret versions when the actor is in a group membership
|
||||
const { username, ...restSearch } = useSearch({
|
||||
strict: false
|
||||
});
|
||||
useEffect(() => {
|
||||
if (username) {
|
||||
setSearch(username);
|
||||
navigate({
|
||||
to: ".",
|
||||
replace: true,
|
||||
search: restSearch
|
||||
});
|
||||
}
|
||||
}, [username]);
|
||||
|
||||
const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp(["assumePrivileges"] as const);
|
||||
|
||||
const handlePerPageChange = (newPerPage: number) => {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
import { zodValidator } from "@tanstack/zod-adapter";
|
||||
import { z } from "zod";
|
||||
|
||||
import { ProjectAccessControlTabs } from "@app/types/project";
|
||||
|
||||
@@ -8,6 +10,11 @@ export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
validateSearch: zodValidator(
|
||||
z.object({
|
||||
username: z.string().optional().catch(undefined)
|
||||
})
|
||||
),
|
||||
beforeLoad: ({ context, params }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState } from "react";
|
||||
import { faEye } from "@fortawesome/free-regular-svg-icons";
|
||||
import {
|
||||
faArrowRotateRight,
|
||||
faBan,
|
||||
faDesktop,
|
||||
faEyeSlash,
|
||||
faServer,
|
||||
@@ -68,10 +69,14 @@ export const SecretVersionItem = ({
|
||||
const getLinkToModifyHistoryEntity = (
|
||||
actorId: string,
|
||||
actorType: string,
|
||||
membershipId: string | null = ""
|
||||
membershipId: string | null = "",
|
||||
groupId: string | null = "",
|
||||
actorName: string | null = ""
|
||||
) => {
|
||||
switch (actorType) {
|
||||
case ActorType.USER:
|
||||
if (groupId)
|
||||
return `/projects/secret-management/${currentProject.id}/groups/${groupId}?username=${actorName}`;
|
||||
return `/projects/secret-management/${currentProject.id}/members/${membershipId}`;
|
||||
case ActorType.IDENTITY:
|
||||
return `/projects/secret-management/${currentProject.id}/identities/${actorId}`;
|
||||
@@ -83,10 +88,26 @@ export const SecretVersionItem = ({
|
||||
const onModifyHistoryClick = (
|
||||
actorId: string | undefined | null,
|
||||
actorType: string | undefined | null,
|
||||
membershipId: string | undefined | null
|
||||
membershipId: string | undefined | null,
|
||||
groupId: string | undefined | null,
|
||||
actorName: string | undefined | null
|
||||
) => {
|
||||
if (!membershipId) {
|
||||
createNotification({
|
||||
type: "info",
|
||||
text: `This ${actorType === ActorType.USER ? "user" : "identity"} is no longer a member of this project.`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (actorType && actorId && actorType !== ActorType.PLATFORM) {
|
||||
const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType, membershipId);
|
||||
const redirectLink = getLinkToModifyHistoryEntity(
|
||||
actorId,
|
||||
actorType,
|
||||
membershipId,
|
||||
groupId,
|
||||
actorName
|
||||
);
|
||||
if (redirectLink) {
|
||||
navigate({ to: redirectLink });
|
||||
}
|
||||
@@ -157,15 +178,33 @@ export const SecretVersionItem = ({
|
||||
<div className="flex flex-row">
|
||||
<div className="flex w-fit flex-row text-sm">
|
||||
Modified by:
|
||||
<Tooltip content={getModifiedByName(actor.actorType, actor.name)}>
|
||||
<Tooltip
|
||||
className="z-[100] max-w-sm"
|
||||
content={
|
||||
getModifiedByName(actor.actorType, actor.name) +
|
||||
(!actor.membershipId && actor.actorId ? " (Removed from project)" : "")
|
||||
}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<div
|
||||
onClick={() =>
|
||||
onModifyHistoryClick(actor.actorId, actor.actorType, actor.membershipId)
|
||||
onClick={
|
||||
actor.membershipId
|
||||
? () =>
|
||||
onModifyHistoryClick(
|
||||
actor.actorId,
|
||||
actor.actorType,
|
||||
actor.membershipId,
|
||||
actor.groupId,
|
||||
actor.name
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
className="cursor-pointer"
|
||||
className={actor.membershipId ? "cursor-pointer" : undefined}
|
||||
>
|
||||
<FontAwesomeIcon icon={getModifiedByIcon(actor.actorType)} className="ml-2" />
|
||||
{!actor.membershipId && (
|
||||
<FontAwesomeIcon className="ml-1 text-mineshaft-400" icon={faBan} />
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user