Merge remote-tracking branch 'origin/main' into pki-revamp

This commit is contained in:
Carlos Monastyrski
2025-10-10 19:58:06 -03:00
942 changed files with 16524 additions and 12472 deletions
@@ -1,4 +1,4 @@
import { useMemo, useState } from "react";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
@@ -55,18 +55,14 @@ const Content = ({ onClose }: ContentProps) => {
const [searchUserFilter, setSearchUserFilter] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useDebounce(searchUserFilter, 500);
const { data, isFetching } = useAdminGetUsers(
{
limit: 20,
searchTerm: debouncedSearchTerm,
adminsOnly: false
},
{
placeholderData: (prev) => prev
}
);
const { data, isPending } = useAdminGetUsers({
limit: 20,
searchTerm: debouncedSearchTerm,
adminsOnly: false
});
const users = useMemo(() => data?.pages.flat().filter((user) => !user.superAdmin) ?? [], [data]);
const { users: usersData = [] } = data ?? {};
const users = usersData.filter((user) => !user.superAdmin);
const onSubmit = async ({ user }: FormData) => {
try {
@@ -91,7 +87,7 @@ const Content = ({ onClose }: ContentProps) => {
render={({ field, fieldState: { error } }) => (
<FormControl isError={Boolean(error)} errorText={error?.message} label="User">
<FilterableSelect
isLoading={searchUserFilter !== debouncedSearchTerm || isFetching}
isLoading={searchUserFilter !== debouncedSearchTerm || isPending}
className="w-full"
placeholder="Search users..."
options={users}
@@ -11,7 +11,6 @@ import {
faXmark
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { InfiniteData } from "@tanstack/react-query";
import { twMerge } from "tailwind-merge";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
@@ -28,6 +27,7 @@ import {
EmptyState,
IconButton,
Input,
Pagination,
Table,
TableContainer,
TableSkeleton,
@@ -39,7 +39,12 @@ import {
Tr
} from "@app/components/v2";
import { useSubscription, useUser } from "@app/context";
import { useDebounce, usePopUp } from "@app/hooks";
import {
getUserTablePreference,
PreferenceKey,
setUserTablePreference
} from "@app/helpers/userTablePreferences";
import { useDebounce, usePagination, usePopUp } from "@app/hooks";
import {
useAdminBulkDeleteUsers,
useAdminDeleteUser,
@@ -54,15 +59,17 @@ const removeServerAdminUpgradePlanMessage = "Removing Server Admin permissions f
const ServerAdminsPanelTable = ({
handlePopUpOpen,
users: usersPages,
users,
isPending,
searchUserFilter,
setSearchUserFilter,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
selectedUsers,
setSelectedUsers
setSelectedUsers,
totalCount,
page,
perPage,
setPage,
handlePerPageChange
}: {
handlePopUpOpen: (
popUpName: keyof UsePopUpState<
@@ -75,20 +82,20 @@ const ServerAdminsPanelTable = ({
}
) => void;
isPending: boolean;
users: InfiniteData<User[], unknown> | undefined;
users?: User[];
searchUserFilter: string;
setSearchUserFilter: (filter: string) => void;
selectedUsers: User[];
setSelectedUsers: Dispatch<SetStateAction<User[]>>;
isFetchingNextPage: boolean;
fetchNextPage: () => void;
hasNextPage: boolean;
totalCount: number;
page: number;
perPage: number;
setPage: Dispatch<SetStateAction<number>>;
handlePerPageChange: (newPerPage: number) => void;
}) => {
const { subscription } = useSubscription();
const users = usersPages?.pages.flat();
const isEmpty = !isPending && !users?.length;
const isEmpty = !isPending && totalCount === 0;
const selectedUserIds = selectedUsers.map((user) => user.id);
@@ -208,7 +215,7 @@ const ServerAdminsPanelTable = ({
<div className="relative">
<FontAwesomeIcon icon={faShieldHalved} />
<FontAwesomeIcon
className="absolute -bottom-[0.01rem] -right-1"
className="absolute -right-1 -bottom-[0.01rem]"
size="2xs"
icon={faXmark}
/>
@@ -241,16 +248,13 @@ const ServerAdminsPanelTable = ({
{!isPending && isEmpty && <EmptyState title="No users found" icon={faUsers} />}
</TableContainer>
{!isEmpty && (
<Button
className="mt-4 py-3 text-sm"
isFullWidth
variant="outline_bg"
isLoading={isFetchingNextPage}
isDisabled={isFetchingNextPage || !hasNextPage}
onClick={() => fetchNextPage()}
>
{hasNextPage ? "Load More" : "End of List"}
</Button>
<Pagination
count={totalCount}
page={page}
perPage={perPage}
onChangePage={(newPage) => setPage(newPage)}
onChangePerPage={handlePerPageChange}
/>
)}
</div>
</>
@@ -278,18 +282,24 @@ export const ServerAdminsTable = () => {
const [searchUserFilter, setSearchUserFilter] = useState("");
const [debouncedSearchTerm] = useDebounce(searchUserFilter, 500);
const {
data: users,
isPending,
isFetchingNextPage,
hasNextPage,
fetchNextPage
} = useAdminGetUsers({
limit: 20,
const { offset, limit, setPage, perPage, page, setPerPage } = usePagination("", {
initPerPage: getUserTablePreference("ServerAdminUsersTable", PreferenceKey.PerPage, 20)
});
const handlePerPageChange = (newPerPage: number) => {
setPerPage(newPerPage);
setUserTablePreference("ServerAdminUsersTable", PreferenceKey.PerPage, newPerPage);
};
const { data, isPending } = useAdminGetUsers({
limit,
offset,
searchTerm: debouncedSearchTerm,
adminsOnly: true
});
const { users = [], totalCount = 0 } = data ?? {};
const handleRemoveUser = async () => {
const { id } = popUp?.removeUser?.data as { id: string; username: string };
@@ -351,7 +361,7 @@ export const ServerAdminsTable = () => {
<>
<div
className={twMerge(
"h-0 flex-shrink-0 overflow-hidden transition-all",
"h-0 shrink-0 overflow-hidden transition-all",
selectedUsers.length > 0 && "h-16"
)}
>
@@ -389,9 +399,11 @@ export const ServerAdminsTable = () => {
searchUserFilter={searchUserFilter}
setSearchUserFilter={setSearchUserFilter}
isPending={isPending}
isFetchingNextPage={isFetchingNextPage}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
page={page}
perPage={perPage}
setPage={setPage}
handlePerPageChange={handlePerPageChange}
totalCount={totalCount}
/>
<DeleteActionModal
isOpen={popUp.removeUser.isOpen}
@@ -433,7 +445,7 @@ export const ServerAdminsTable = () => {
<div className="mt-4 text-sm text-mineshaft-400">
The following users will be deleted:
</div>
<div className="mt-2 max-h-[20rem] overflow-y-auto rounded border border-mineshaft-600 bg-red/10 p-4 pl-8 text-sm text-red-200">
<div className="mt-2 max-h-80 overflow-y-auto rounded-sm border border-mineshaft-600 bg-red/10 p-4 pl-8 text-sm text-red-200">
<ul className="list-disc">
{selectedUsers?.map((user) => {
const email = user.email ?? user.username;
@@ -455,7 +467,7 @@ export const ServerAdminsTable = () => {
<div className="inline-block">
<Badge
variant="primary"
className="ml-1 mt-[0.05rem] inline-flex w-min items-center gap-1.5 whitespace-nowrap"
className="mt-[0.05rem] ml-1 inline-flex w-min items-center gap-1.5 whitespace-nowrap"
>
<FontAwesomeIcon icon={faWarning} />
<span>Deleting Yourself</span>
@@ -115,7 +115,7 @@ export const AuthenticationPageForm = () => {
onSubmit={handleSubmit(onAuthFormSubmit)}
>
<div className="flex flex-col justify-start">
<div className="mb-2 text-xl font-semibold text-mineshaft-100">Login Methods</div>
<div className="mb-2 text-xl font-medium text-mineshaft-100">Login Methods</div>
<div className="mb-4 max-w-sm text-sm text-mineshaft-400">
Select the login methods you wish to allow for all users of this instance.
</div>
@@ -60,7 +60,7 @@ export const CachingPageForm = () => {
<div className="mb-6 flex flex-wrap items-end justify-between gap-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex flex-col">
<div className="mb-2 flex items-center gap-3">
<span className="text-xl font-semibold text-mineshaft-100">Secrets Cache</span>
<span className="text-xl font-medium text-mineshaft-100">Secrets Cache</span>
{isInvalidating && (
<Badge
variant="danger"
@@ -82,7 +82,7 @@ export const EncryptionPageForm = () => {
>
<div className="flex flex-col justify-start">
<div className="flex w-full justify-between">
<div className="mb-2 text-xl font-semibold text-mineshaft-100">
<div className="mb-2 text-xl font-medium text-mineshaft-100">
KMS Encryption Strategy
</div>
</div>
@@ -58,7 +58,7 @@ export const GroupContainer = ({
icon={faChevronRight}
/>
<div className="flex-grow select-none text-base">{group.name}</div>
<div className="grow text-base select-none">{group.name}</div>
</div>
{(open || search) && (
@@ -214,13 +214,13 @@ export const EnvironmentPageForm = () => {
<div className="flex w-full flex-row items-center justify-between">
<div>
<div className="flex items-start gap-1">
<p className="text-xl font-semibold text-mineshaft-100">Overrides</p>
<p className="text-xl font-medium text-mineshaft-100">Overrides</p>
<a
href="https://infisical.com/docs/self-hosting/configuration/envars#environment-variable-overrides"
target="_blank"
rel="noopener noreferrer"
>
<div className="ml-1 mt-[0.32rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<div className="mt-[0.32rem] ml-1 inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
@@ -107,7 +107,7 @@ export const GeneralPageForm = () => {
onSubmit={handleSubmit(onFormSubmit)}
>
<div className="flex flex-col justify-start">
<div className="mb-2 text-xl font-semibold text-mineshaft-100">Allow user signups</div>
<div className="mb-2 text-xl font-medium text-mineshaft-100">Allow user signups</div>
<div className="mb-4 max-w-sm text-sm text-mineshaft-400">
Select if you want users to be able to signup freely into your Infisical instance.
</div>
@@ -132,7 +132,7 @@ export const GeneralPageForm = () => {
</div>
{signUpMode === "anyone" && (
<div className="flex flex-col justify-start">
<div className="mb-4 text-xl font-semibold text-mineshaft-100">
<div className="mb-4 text-xl font-medium text-mineshaft-100">
Restrict signup by email domain(s)
</div>
<Controller
@@ -159,7 +159,7 @@ export const GeneralPageForm = () => {
)}
<div className="flex flex-col justify-start">
<div className="mb-2 text-xl font-semibold text-mineshaft-100">Default organization</div>
<div className="mb-2 text-xl font-medium text-mineshaft-100">Default organization</div>
<div className="mb-4 max-w-sm text-sm text-mineshaft-400">
Select the default organization you want to set for SAML/LDAP/OIDC/Github logins. When
selected, user logins will be automatically scoped to the selected organization.
@@ -197,7 +197,7 @@ export const GeneralPageForm = () => {
</div>
<div className="flex flex-col justify-start">
<div className="mb-2 text-xl font-semibold text-mineshaft-100">Trust emails</div>
<div className="mb-2 text-xl font-medium text-mineshaft-100">Trust emails</div>
<div className="mb-4 max-w-sm text-sm text-mineshaft-400">
Select if you want Infisical to trust external emails from SAML/LDAP/OIDC identity
providers. If set to false, then Infisical will prompt SAML/LDAP/OIDC provisioned users to
@@ -257,7 +257,7 @@ export const GeneralPageForm = () => {
</div>
<div className="flex flex-col justify-start">
<div className="mb-2 text-xl font-semibold text-mineshaft-100">Notices</div>
<div className="mb-2 text-xl font-medium text-mineshaft-100">Notices</div>
<div className="mb-4 max-w-lg text-sm text-mineshaft-400">
Configure system-wide notification banners and security messages. These settings control
the text displayed to users during authentication and throughout their session
@@ -274,7 +274,7 @@ export const GeneralPageForm = () => {
placeholder="**Auth Consent Message**"
{...field}
rows={3}
className="thin-scrollbar h-48 max-w-lg !resize-none bg-mineshaft-800"
className="h-48 thin-scrollbar max-w-lg resize-none! bg-mineshaft-800"
/>
</FormControl>
)}
@@ -293,7 +293,7 @@ export const GeneralPageForm = () => {
placeholder='<div style="background-color: red">TOP SECRET</div>'
{...field}
rows={3}
className="thin-scrollbar h-48 max-w-lg !resize-none bg-mineshaft-800"
className="h-48 thin-scrollbar max-w-lg resize-none! bg-mineshaft-800"
/>
</FormControl>
)}
@@ -53,7 +53,7 @@ export const IntegrationsPageForm = () => {
return (
<div className="mb-6 min-h-64 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4">
<div className="text-xl font-semibold text-mineshaft-100">Integrations</div>
<div className="text-xl font-medium text-mineshaft-100">Integrations</div>
<div className="text-sm text-mineshaft-300">
Configure your instance-wide settings to enable integration with third-party services.
</div>
@@ -75,7 +75,7 @@ export const MicrosoftTeamsIntegrationForm = ({ adminIntegrationsConfig }: Props
<AccordionTrigger className="flex h-fit w-full justify-start rounded-md border border-mineshaft-500 bg-mineshaft-700 px-4 py-6 text-sm transition-colors data-[state=open]:rounded-b-none">
<div className="text-md group order-1 ml-3 flex items-center gap-2">
<BsMicrosoftTeams className="text-lg group-hover:text-primary-400" />
<div className="text-[15px] font-semibold">Microsoft Teams</div>
<div className="text-[15px] font-medium">Microsoft Teams</div>
</div>
</AccordionTrigger>
<AccordionContent childrenClassName="px-0 py-0">
@@ -29,7 +29,7 @@ const getCustomSlackAppCreationUrl = () =>
- Notifications: Receive real-time updates and alerts about critical events in your Infisical projects. Whether it's a new project being created, updates to secrets, or changes to your team's configuration, you will be promptly notified within the designated Slack channels of your choice.
- Customization: Tailor the notifications to your team's specific needs by configuring which types of events trigger alerts and in which channels they are sent.
- Collaboration: Keep your entire team in the loop with notifications that help facilitate more efficient collaboration by ensuring that everyone is aware of important developments in your Infisical projects.
By integrating Infisical with Slack, you can enhance your workflow by combining the power of secure secrets management with the communication capabilities of Slack.`
},
features: {
@@ -108,7 +108,7 @@ export const SlackIntegrationForm = ({ adminIntegrationsConfig }: Props) => {
<AccordionTrigger className="flex h-fit w-full justify-start rounded-md border border-mineshaft-500 bg-mineshaft-700 px-4 py-6 text-sm transition-colors data-[state=open]:rounded-b-none">
<div className="text-md group order-1 ml-3 flex items-center gap-2">
<BsSlack className="text-lg group-hover:text-primary-400" />
<div className="text-[15px] font-semibold">Slack</div>
<div className="text-[15px] font-medium">Slack</div>
</div>
</AccordionTrigger>
<AccordionContent childrenClassName="px-0 py-0">
@@ -1,4 +1,4 @@
import { useMemo, useState } from "react";
import { useState } from "react";
import { Controller, useFieldArray, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
@@ -72,18 +72,13 @@ const Content = ({ onClose }: ContentProps) => {
const [searchUserFilter, setSearchUserFilter] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useDebounce(searchUserFilter, 500);
const { data, isFetching } = useAdminGetUsers(
{
limit: 20,
searchTerm: debouncedSearchTerm,
adminsOnly: false
},
{
placeholderData: (prev) => prev
}
);
const { data, isPending } = useAdminGetUsers({
limit: 20,
searchTerm: debouncedSearchTerm,
adminsOnly: false
});
const users = useMemo(() => data?.pages.flat() ?? [], [data]);
const { users = [] } = data ?? {};
const onSubmit = async ({ name, invitees }: FormData) => {
try {
@@ -155,7 +150,7 @@ const Content = ({ onClose }: ContentProps) => {
})
.includes(input)
}
isLoading={searchUserFilter !== debouncedSearchTerm || isFetching}
isLoading={searchUserFilter !== debouncedSearchTerm || isPending}
className="w-full"
placeholder="Search users or invite new ones..."
isMulti
@@ -11,7 +11,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createNotification } from "@app/components/notifications";
import {
Badge,
Button,
DeleteActionModal,
DropdownMenu,
DropdownMenuContent,
@@ -20,6 +19,7 @@ import {
EmptyState,
IconButton,
Input,
Pagination,
Table,
TableContainer,
TableSkeleton,
@@ -29,7 +29,12 @@ import {
THead,
Tr
} from "@app/components/v2";
import { useDebounce, usePopUp } from "@app/hooks";
import {
getUserTablePreference,
PreferenceKey,
setUserTablePreference
} from "@app/helpers/userTablePreferences";
import { useDebounce, usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
import { useAdminRemoveIdentitySuperAdminAccess } from "@app/hooks/api/admin";
import { useAdminGetIdentities } from "@app/hooks/api/admin/queries";
import { UsePopUpState } from "@app/hooks/usePopUp";
@@ -48,14 +53,34 @@ const IdentityPanelTable = ({
const [searchIdentityFilter, setSearchIdentityFilter] = useState("");
const [debouncedSearchTerm] = useDebounce(searchIdentityFilter, 500);
const { data, isPending, isFetchingNextPage, hasNextPage, fetchNextPage } = useAdminGetIdentities(
{
limit: 20,
searchTerm: debouncedSearchTerm
}
);
const { offset, limit, setPage, perPage, page, setPerPage } = usePagination("", {
initPerPage: getUserTablePreference(
"ResourceOverviewIdentitiesTable",
PreferenceKey.PerPage,
10
)
});
const isEmpty = !isPending && !data?.pages?.[0].length;
const handlePerPageChange = (newPerPage: number) => {
setPerPage(newPerPage);
setUserTablePreference("ResourceOverviewIdentitiesTable", PreferenceKey.PerPage, newPerPage);
};
const { data, isPending } = useAdminGetIdentities({
limit,
offset,
searchTerm: debouncedSearchTerm
});
const { identities, totalCount = 0 } = data ?? {};
const isEmpty = !isPending && !totalCount;
useResetPageHelper({
totalCount,
offset,
setPage
});
return (
<>
@@ -80,75 +105,68 @@ const IdentityPanelTable = ({
<TBody>
{isPending && <TableSkeleton columns={2} innerKey="identities" />}
{!isPending &&
data?.pages?.map((identities) =>
identities.map(({ name, id, isInstanceAdmin }) => (
<Tr key={`identity-${id}`} className="w-full">
<Td>
{name}
{isInstanceAdmin && (
<Badge variant="primary" className="ml-2">
Server Admin
</Badge>
)}
</Td>
<Td>
{isInstanceAdmin && (
<div className="flex justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent sideOffset={2} align="end">
{isInstanceAdmin && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handlePopUpOpen("removeServerAdmin", { name, id });
}}
icon={
<div className="relative">
<FontAwesomeIcon icon={faShieldHalved} />
<FontAwesomeIcon
className="absolute -bottom-[0.01rem] -right-1"
size="2xs"
icon={faXmark}
/>
</div>
}
>
Remove Server Admin
</DropdownMenuItem>
)}
</DropdownMenuContent>
</DropdownMenu>
</div>
)}
</Td>
</Tr>
))
)}
identities?.map(({ name, id, isInstanceAdmin }) => (
<Tr key={`identity-${id}`} className="w-full">
<Td>
{name}
{isInstanceAdmin && (
<Badge variant="primary" className="ml-2">
Server Admin
</Badge>
)}
</Td>
<Td>
{isInstanceAdmin && (
<div className="flex justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent sideOffset={2} align="end">
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handlePopUpOpen("removeServerAdmin", { name, id });
}}
icon={
<div className="relative">
<FontAwesomeIcon icon={faShieldHalved} />
<FontAwesomeIcon
className="absolute -right-1 -bottom-[0.01rem]"
size="2xs"
icon={faXmark}
/>
</div>
}
>
Remove Server Admin
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)}
</Td>
</Tr>
))}
</TBody>
</Table>
{!isPending && isEmpty && <EmptyState title="No identities found" icon={faWrench} />}
</TableContainer>
{!isEmpty && (
<Button
className="mt-4 py-3 text-sm"
isFullWidth
variant="outline_bg"
isLoading={isFetchingNextPage}
isDisabled={isFetchingNextPage || !hasNextPage}
onClick={() => fetchNextPage()}
>
{hasNextPage ? "Load More" : "End of List"}
</Button>
{!isPending && totalCount > 0 && (
<Pagination
count={totalCount}
page={page}
perPage={perPage}
onChangePage={(newPage) => setPage(newPage)}
onChangePerPage={handlePerPageChange}
/>
)}
</div>
</>
@@ -185,7 +203,7 @@ export const MachineIdentitiesTable = () => {
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div>
<p className="text-xl font-semibold text-mineshaft-100">Machine Identities</p>
<p className="text-xl font-medium text-mineshaft-100">Machine Identities</p>
<p className="text-sm text-bunker-300">Manage machine identities across your instance.</p>
</div>
</div>
@@ -48,6 +48,11 @@ import {
} from "@app/components/v2";
import { useUser } from "@app/context";
import { OrgMembershipRole } from "@app/helpers/roles";
import {
getUserTablePreference,
PreferenceKey,
setUserTablePreference
} from "@app/helpers/userTablePreferences";
import { useDebounce, usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
import {
useAdminDeleteOrganization,
@@ -291,7 +296,7 @@ const ViewMembersModalContent = ({
</div>
</Td>
<Td className="max-w-0">
<Badge className="flex w-fit max-w-full items-center gap-x-1 whitespace-nowrap bg-mineshaft-400/50 text-bunker-200">
<Badge className="flex w-fit max-w-full items-center gap-x-1 bg-mineshaft-400/50 whitespace-nowrap text-bunker-200">
<p className="truncate capitalize">{member.role.replace("-", " ")}</p>
{Boolean(member.roleId) && (
<Tooltip content="This member has a custom role assigned.">
@@ -443,13 +448,31 @@ const OrganizationsPanelTable = ({
const { user } = useUser();
const navigate = useNavigate();
const { data, isPending, isFetchingNextPage, hasNextPage, fetchNextPage } =
useAdminGetOrganizations({
limit: 20,
searchTerm: debouncedSearchTerm
});
const isEmpty = !isPending && !data?.pages?.[0].length;
const { offset, limit, setPage, perPage, page, setPerPage } = usePagination("", {
initPerPage: getUserTablePreference("ResourceOverviewOrgsTable", PreferenceKey.PerPage, 10)
});
const handlePerPageChange = (newPerPage: number) => {
setPerPage(newPerPage);
setUserTablePreference("ResourceOverviewOrgsTable", PreferenceKey.PerPage, newPerPage);
};
const { data, isPending } = useAdminGetOrganizations({
limit,
offset,
searchTerm: debouncedSearchTerm
});
const { organizations, totalCount = 0 } = data ?? {};
const isEmpty = !isPending && !totalCount;
useResetPageHelper({
totalCount,
offset,
setPage
});
const { mutateAsync: accessOrganization } = useServerAdminAccessOrg();
@@ -499,125 +522,120 @@ const OrganizationsPanelTable = ({
<TBody>
{isPending && <TableSkeleton columns={4} innerKey="organizations" />}
{!isPending &&
data?.pages?.map((orgs) =>
orgs.map((org) => {
const isMember = org.members.find((member) => member.user.id === user.id);
organizations?.map((org) => {
const isMember = org.members.find((member) => member.user.id === user.id);
return (
<Tr key={`org-${org.id}`} className="w-full">
<Td className="w-1/2 max-w-0">
<div className="flex items-center gap-x-1.5">
{org.name ? (
<p className="truncate">{org.name}</p>
) : (
<span className="text-mineshaft-400">Not Set</span>
)}
</div>
</Td>
<Td className="w-1/3">
<button
type="button"
onClick={() => handlePopUpOpen("viewMembers", { organization: org })}
className="flex items-center hover:underline"
>
<Tooltip className="text-center" content="View Members">
<FontAwesomeIcon
icon={faEye}
className="mr-1.5 text-mineshaft-300"
size="sm"
/>
return (
<Tr key={`org-${org.id}`} className="w-full">
<Td className="w-1/2 max-w-0">
<div className="flex items-center gap-x-1.5">
{org.name ? (
<p className="truncate">{org.name}</p>
) : (
<span className="text-mineshaft-400">Not Set</span>
)}
</div>
</Td>
<Td className="w-1/3">
<button
type="button"
onClick={() => handlePopUpOpen("viewMembers", { organization: org })}
className="flex items-center hover:underline"
>
<Tooltip className="text-center" content="View Members">
<FontAwesomeIcon
icon={faEye}
className="mr-1.5 text-mineshaft-300"
size="sm"
/>
</Tooltip>
{org.members.length} {org.members.length === 1 ? "Member" : "Members"}
{!org.members.some(
(member) =>
member.role === OrgMembershipRole.Admin &&
member.status === OrgMembershipStatus.Accepted
) && (
<Tooltip content="No admins have accepted their invitations.">
<div className="ml-1.5">
<FontAwesomeIcon className="text-yellow" icon={faWarning} />
</div>
</Tooltip>
{org.members.length} {org.members.length === 1 ? "Member" : "Members"}
{!org.members.some(
(member) =>
member.role === OrgMembershipRole.Admin &&
member.status === OrgMembershipStatus.Accepted
) && (
<Tooltip content="No admins have accepted their invitations.">
<div className="ml-1.5">
<FontAwesomeIcon className="text-yellow" icon={faWarning} />
</div>
</Tooltip>
)}
</button>
</Td>
<Td className="w-1/3">
{org.projects.length} {org.projects.length === 1 ? "Project" : "Projects"}
</Td>
<Td>
<div className="flex justify-end gap-x-1">
{isMember && (
<Tooltip
className="text-center"
content="You are a member of this organization"
)}
</button>
</Td>
<Td className="w-1/3">
{org.projects.length} {org.projects.length === 1 ? "Project" : "Projects"}
</Td>
<Td>
<div className="flex justify-end gap-x-1">
{isMember && (
<Tooltip
className="text-center"
content="You are a member of this organization"
>
<div>
<FontAwesomeIcon
className="text-mineshaft-400"
icon={faUserCheck}
size="sm"
/>
</div>
</Tooltip>
)}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<div>
<FontAwesomeIcon
className="text-mineshaft-400"
icon={faUserCheck}
size="sm"
/>
</div>
</Tooltip>
)}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent sideOffset={2} align="end">
{!isMember && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handleAccessOrg(org.id);
}}
icon={<FontAwesomeIcon icon={faUserPlus} />}
>
Join Organization
</DropdownMenuItem>
)}
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent sideOffset={2} align="end">
{!isMember && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handlePopUpOpen("deleteOrganization", {
orgId: org.id,
orgName: org.name
});
handleAccessOrg(org.id);
}}
icon={<FontAwesomeIcon icon={faTrash} />}
icon={<FontAwesomeIcon icon={faUserPlus} />}
>
Delete Organization
Join Organization
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</Td>
</Tr>
);
})
)}
)}
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handlePopUpOpen("deleteOrganization", {
orgId: org.id,
orgName: org.name
});
}}
icon={<FontAwesomeIcon icon={faTrash} />}
>
Delete Organization
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</Td>
</Tr>
);
})}
</TBody>
</Table>
{!isPending && isEmpty && <EmptyState title="No organizations found" icon={faBuilding} />}
</TableContainer>
{!isEmpty && (
<Button
className="mt-4 py-3 text-sm"
isFullWidth
variant="outline_bg"
isLoading={isFetchingNextPage}
isDisabled={isFetchingNextPage || !hasNextPage}
onClick={() => fetchNextPage()}
>
{hasNextPage ? "Load More" : "End of list"}
</Button>
{!isPending && totalCount > 0 && (
<Pagination
count={totalCount}
page={page}
perPage={perPage}
onChangePage={(newPage) => setPage(newPage)}
onChangePerPage={handlePerPageChange}
/>
)}
</div>
<ViewMembersModal
@@ -696,7 +714,7 @@ export const OrganizationsTable = () => {
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div>
<p className="text-xl font-semibold text-mineshaft-100">Organizations</p>
<p className="text-xl font-medium text-mineshaft-100">Organizations</p>
<p className="text-sm text-bunker-300">
Manage, join and view organizations across your instance.
</p>
@@ -13,7 +13,6 @@ import {
faXmark
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { InfiniteData } from "@tanstack/react-query";
import { twMerge } from "tailwind-merge";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
@@ -31,6 +30,7 @@ import {
EmptyState,
IconButton,
Input,
Pagination,
Table,
TableContainer,
TableSkeleton,
@@ -42,7 +42,12 @@ import {
Tr
} from "@app/components/v2";
import { useSubscription, useUser } from "@app/context";
import { useDebounce, usePopUp } from "@app/hooks";
import {
getUserTablePreference,
PreferenceKey,
setUserTablePreference
} from "@app/helpers/userTablePreferences";
import { useDebounce, usePagination, usePopUp } from "@app/hooks";
import {
useAdminBulkDeleteUsers,
useAdminDeleteUser,
@@ -58,17 +63,19 @@ const removeServerAdminUpgradePlanMessage = "Removing Server Admin permissions f
const UserPanelTable = ({
handlePopUpOpen,
users: usersPages,
users,
isPending,
adminsOnly,
searchUserFilter,
setSearchUserFilter,
setAdminsOnly,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
selectedUsers,
setSelectedUsers
setSelectedUsers,
totalCount,
page,
perPage,
setPage,
handlePerPageChange
}: {
handlePopUpOpen: (
popUpName: keyof UsePopUpState<
@@ -81,22 +88,22 @@ const UserPanelTable = ({
}
) => void;
isPending: boolean;
users: InfiniteData<User[], unknown> | undefined;
users: User[] | undefined;
adminsOnly: boolean;
setAdminsOnly: (adminsOnly: boolean) => void;
searchUserFilter: string;
setSearchUserFilter: (filter: string) => void;
selectedUsers: User[];
setSelectedUsers: Dispatch<SetStateAction<User[]>>;
isFetchingNextPage: boolean;
fetchNextPage: () => void;
hasNextPage: boolean;
totalCount: number;
page: number;
perPage: number;
setPage: Dispatch<SetStateAction<number>>;
handlePerPageChange: (newPerPage: number) => void;
}) => {
const { subscription } = useSubscription();
const users = usersPages?.pages.flat();
const isEmpty = !isPending && !users?.length;
const isEmpty = !isPending && totalCount === 0;
const isTableFiltered = Boolean(adminsOnly);
const selectedUserIds = selectedUsers.map((user) => user.id);
@@ -268,7 +275,7 @@ const UserPanelTable = ({
<div className="relative">
<FontAwesomeIcon icon={faShieldHalved} />
<FontAwesomeIcon
className="absolute -bottom-[0.01rem] -right-1"
className="absolute -right-1 -bottom-[0.01rem]"
size="2xs"
icon={faXmark}
/>
@@ -302,16 +309,13 @@ const UserPanelTable = ({
{!isPending && isEmpty && <EmptyState title="No users found" icon={faUsers} />}
</TableContainer>
{!isEmpty && (
<Button
className="mt-4 py-3 text-sm"
isFullWidth
variant="outline_bg"
isLoading={isFetchingNextPage}
isDisabled={isFetchingNextPage || !hasNextPage}
onClick={() => fetchNextPage()}
>
{hasNextPage ? "Load More" : "End of List"}
</Button>
<Pagination
count={totalCount}
page={page}
perPage={perPage}
onChangePage={(newPage) => setPage(newPage)}
onChangePerPage={handlePerPageChange}
/>
)}
</div>
</>
@@ -341,18 +345,24 @@ export const UserIdentitiesTable = () => {
const [adminsOnly, setAdminsOnly] = useState(false);
const [debouncedSearchTerm] = useDebounce(searchUserFilter, 500);
const {
data: users,
isPending,
isFetchingNextPage,
hasNextPage,
fetchNextPage
} = useAdminGetUsers({
limit: 20,
const { offset, limit, setPage, perPage, page, setPerPage } = usePagination("", {
initPerPage: getUserTablePreference("ResourceOverviewUsersTable", PreferenceKey.PerPage, 20)
});
const handlePerPageChange = (newPerPage: number) => {
setPerPage(newPerPage);
setUserTablePreference("ResourceOverviewUsersTable", PreferenceKey.PerPage, newPerPage);
};
const { data, isPending } = useAdminGetUsers({
limit,
offset,
searchTerm: debouncedSearchTerm,
adminsOnly
});
const { users, totalCount = 0 } = data ?? {};
const handleRemoveUser = async () => {
const { id } = popUp?.removeUser?.data as { id: string; username: string };
@@ -433,7 +443,7 @@ export const UserIdentitiesTable = () => {
<>
<div
className={twMerge(
"h-0 flex-shrink-0 overflow-hidden transition-all",
"h-0 shrink-0 overflow-hidden transition-all",
selectedUsers.length > 0 && "h-16"
)}
>
@@ -465,7 +475,7 @@ export const UserIdentitiesTable = () => {
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div>
<p className="text-xl font-semibold text-mineshaft-100">User Identities</p>
<p className="text-xl font-medium text-mineshaft-100">User Identities</p>
<p className="text-sm text-bunker-300">Manage user identities across your instance.</p>
</div>
</div>
@@ -479,9 +489,11 @@ export const UserIdentitiesTable = () => {
isPending={isPending}
adminsOnly={adminsOnly}
setAdminsOnly={setAdminsOnly}
isFetchingNextPage={isFetchingNextPage}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
page={page}
perPage={perPage}
setPage={setPage}
handlePerPageChange={handlePerPageChange}
totalCount={totalCount}
/>
<DeleteActionModal
isOpen={popUp.removeUser.isOpen}
@@ -530,7 +542,7 @@ export const UserIdentitiesTable = () => {
<div className="mt-4 text-sm text-mineshaft-400">
The following users will be deleted:
</div>
<div className="mt-2 max-h-[20rem] overflow-y-auto rounded border border-mineshaft-600 bg-red/10 p-4 pl-8 text-sm text-red-200">
<div className="mt-2 max-h-80 overflow-y-auto rounded-sm border border-mineshaft-600 bg-red/10 p-4 pl-8 text-sm text-red-200">
<ul className="list-disc">
{selectedUsers?.map((user) => {
const email = user.email ?? user.username;
@@ -552,7 +564,7 @@ export const UserIdentitiesTable = () => {
<div className="inline-block">
<Badge
variant="primary"
className="ml-1 mt-[0.05rem] inline-flex w-min items-center gap-1.5 whitespace-nowrap"
className="mt-[0.05rem] ml-1 inline-flex w-min items-center gap-1.5 whitespace-nowrap"
>
<FontAwesomeIcon icon={faWarning} />
<span>Deleting Yourself</span>
@@ -74,7 +74,7 @@ export const SignUpPage = () => {
if (config?.initialized) return <ContentLoader text="Redirecting to admin page..." />;
return (
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6">
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6">
<Helmet>
<title>{t("common.head-title", { title: t("signup.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -54,7 +54,7 @@ export const CliRedirectPage = () => {
{cliToken ? (
<>
<div className="pb-4">
<p className="bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-3xl font-medium text-transparent">
<p className="bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-3xl font-medium text-transparent">
Unable to reach CLI
</p>
<p className="text-light mb-1 text-center text-lg text-mineshaft-400">
@@ -73,7 +73,7 @@ export const CliRedirectPage = () => {
colorSchema="primary"
ariaLabel="copy to clipboard"
onClick={copyUrlToClipboard}
className="flex items-center rounded py-2"
className="flex items-center rounded-sm py-2"
>
<FontAwesomeIcon className="pr-2" icon={isUrlCopied ? faCheck : faCopy} /> Copy to
clipboard
@@ -83,7 +83,7 @@ export const CliRedirectPage = () => {
</>
) : (
<>
<p className="bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-3xl font-medium text-transparent">
<p className="bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-3xl font-medium text-transparent">
Head back to your terminal
</p>
<p className="text-light mb-1 text-lg text-mineshaft-400">
@@ -3,18 +3,18 @@ import { Link } from "@tanstack/react-router";
export const EmailNotVerifiedPage = () => {
return (
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex min-h-screen flex-col justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet>
<title>Request a New Invite</title>
<link rel="icon" href="/infisical.ico" />
</Helmet>
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img src="/images/gradientLogo.svg" className="h-[90px] w-[120px]" alt="Infisical Logo" />
</div>
</Link>
<div className="mx-auto flex w-full flex-col items-center justify-center">
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Your email was not verified
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
@@ -62,7 +62,7 @@ export const LoginLdapPage = () => {
};
return (
<div className="flex h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex h-screen flex-col justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet>
<title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -71,7 +71,7 @@ export const LoginLdapPage = () => {
<meta name="og:description" content={t("login.og-description") ?? ""} />
</Helmet>
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img
src="/images/gradientLogo.svg"
style={{
@@ -83,12 +83,12 @@ export const LoginLdapPage = () => {
</div>
</Link>
<div className="mx-auto w-full max-w-md md:px-6">
<p className="mx-auto mb-8 flex w-max justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<p className="mx-auto mb-8 flex w-max justify-center bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
What&apos;s your LDAP Login?
</p>
<form onSubmit={handleSubmission}>
{!config.defaultAuthOrgSlug && !passedOrgSlug && (
<div className="relative mx-auto flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-[22rem] lg:w-1/6">
<div className="relative mx-auto flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-88 lg:w-1/6">
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:max-h-28">
<Input
value={organizationSlug}
@@ -103,7 +103,7 @@ export const LoginLdapPage = () => {
</div>
</div>
)}
<div className="relative mx-auto mt-2 flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-[22rem] lg:w-1/6">
<div className="relative mx-auto mt-2 flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-88 lg:w-1/6">
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:max-h-28">
<Input
value={username}
@@ -118,7 +118,7 @@ export const LoginLdapPage = () => {
/>
</div>
</div>
<div className="relative mx-auto mt-2 flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-[22rem] lg:w-1/6">
<div className="relative mx-auto mt-2 flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-88 lg:w-1/6">
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:max-h-28">
<Input
value={password}
@@ -132,7 +132,7 @@ export const LoginLdapPage = () => {
/>
</div>
</div>
<div className="mx-auto mt-4 flex w-full min-w-[20rem] items-center justify-center rounded-md text-center md:min-w-[22rem] lg:w-1/6">
<div className="mx-auto mt-4 flex w-full min-w-[20rem] items-center justify-center rounded-md text-center md:min-w-88 lg:w-1/6">
<Button
type="submit"
colorSchema="primary"
@@ -64,7 +64,7 @@ export const LoginPage = ({ isAdmin }: { isAdmin?: boolean }) => {
};
return (
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6">
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6">
<Helmet>
<title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -73,7 +73,7 @@ export const LoginPage = ({ isAdmin }: { isAdmin?: boolean }) => {
<meta name="og:description" content={t("login.og-description") ?? ""} />
</Helmet>
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img
src="/images/gradientLogo.svg"
style={{
@@ -176,7 +176,7 @@ export const InitialStep = ({
onSubmit={handleLogin}
className="mx-auto flex w-full flex-col items-center justify-center"
>
<h1 className="mb-8 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-8 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Login to Infisical
</h1>
<RegionSelect />
@@ -215,7 +215,7 @@ export const InitialStep = ({
onSubmit={handleLogin}
className="mx-auto flex w-full flex-col items-center justify-center"
>
<h1 className="mb-8 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-8 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Login to Infisical
</h1>
<RegionSelect />
@@ -301,7 +301,7 @@ export const PasswordStep = ({
if (shouldShowMfa) {
return (
<div className="flex max-h-screen min-h-screen flex-col items-center justify-center gap-2 overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<div className="flex max-h-screen min-h-screen flex-col items-center justify-center gap-2 overflow-y-auto bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<Mfa
email={email}
successCallback={mfaSuccessCallback}
@@ -326,7 +326,7 @@ export const PasswordStep = ({
if (hasExchangedPrivateKey) {
return (
<div className="fixed left-0 top-0 h-screen w-screen bg-bunker-800">
<div className="fixed top-0 left-0 h-screen w-screen bg-bunker-800">
<ContentLoader />
</div>
);
@@ -335,11 +335,11 @@ export const PasswordStep = ({
return (
<form onSubmit={handleLogin} className="mx-auto h-full w-full max-w-md px-6 pt-8">
<div className="mb-8">
<p className="mx-auto mb-4 flex w-max justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<p className="mx-auto mb-4 flex w-max justify-center bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
What&apos;s your Infisical password?
</p>
</div>
<div className="relative mx-auto flex max-h-24 w-full min-w-[22rem] items-center justify-center rounded-lg md:max-h-28 lg:w-1/6">
<div className="relative mx-auto flex max-h-24 w-full min-w-88 items-center justify-center rounded-lg md:max-h-28 lg:w-1/6">
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:max-h-28">
<Input
value={password}
@@ -354,7 +354,7 @@ export const PasswordStep = ({
</div>
</div>
{shouldShowCaptcha && envConfig.CAPTCHA_SITE_KEY && (
<div className="mx-auto mt-4 flex w-full min-w-[22rem] items-center justify-center lg:w-1/6">
<div className="mx-auto mt-4 flex w-full min-w-88 items-center justify-center lg:w-1/6">
<HCaptcha
theme="dark"
sitekey={envConfig.CAPTCHA_SITE_KEY}
@@ -363,7 +363,7 @@ export const PasswordStep = ({
/>
</div>
)}
<div className="mx-auto mt-4 flex w-full min-w-[22rem] items-center justify-center rounded-md text-center lg:w-1/6">
<div className="mx-auto mt-4 flex w-full min-w-88 items-center justify-center rounded-md text-center lg:w-1/6">
<Button
disabled={shouldShowCaptcha && captchaToken === ""}
type="submit"
@@ -36,11 +36,11 @@ export const SSOStep = ({ setStep, type }: Props) => {
return (
<div className="mx-auto w-full max-w-md md:px-6">
<p className="mx-auto mb-8 flex w-max justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<p className="mx-auto mb-8 flex w-max justify-center bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
What&apos;s your organization slug?
</p>
<form onSubmit={handleSubmission}>
<div className="relative mx-auto flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-[22rem] lg:w-1/6">
<div className="relative mx-auto flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-88 lg:w-1/6">
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:max-h-28">
<Input
value={ssoIdentifier}
@@ -54,7 +54,7 @@ export const SSOStep = ({ setStep, type }: Props) => {
/>
</div>
</div>
<div className="mx-auto mt-4 flex w-full min-w-[20rem] items-center justify-center rounded-md text-center md:min-w-[22rem] lg:w-1/6">
<div className="mx-auto mt-4 flex w-full min-w-[20rem] items-center justify-center rounded-md text-center md:min-w-88 lg:w-1/6">
<Button
type="submit"
colorSchema="primary"
@@ -43,7 +43,7 @@ export const LoginSsoPage = () => {
};
return (
<div className="flex h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex h-screen flex-col justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet>
<title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -52,7 +52,7 @@ export const LoginSsoPage = () => {
<meta name="og:description" content={t("login.og-description") ?? ""} />
</Helmet>
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img
src="/images/gradientLogo.svg"
style={{ height: "90px", width: "120px" }}
@@ -36,9 +36,9 @@ export const PasswordResetPage = () => {
const navigate = useNavigate();
return (
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex min-h-screen flex-col justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img src="/images/gradientLogo.svg" className="h-[90px] w-[120px]" alt="Infisical Logo" />
</div>
</Link>
@@ -20,7 +20,7 @@ export const ConfirmEmailStep = ({ onComplete }: Props) => {
} = useVerifyPasswordResetCode();
return (
<div className="mx-auto flex w-full flex-col items-center justify-center">
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Confirm your email
</h1>
<p className="mb-8 w-max justify-center text-center text-sm text-gray-400">
@@ -171,7 +171,7 @@ export const EnterPasswordStep = ({
onSubmit={handleSubmit(resetPasswordHandler)}
className="mx-auto flex w-full flex-col items-center justify-center"
>
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Enter new password
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
@@ -222,7 +222,7 @@ export const EnterPasswordStep = ({
passwordErrorEscapeChar ||
passwordErrorLowEntropy ||
passwordErrorBreached ? (
<div className="mt-4 rounded border border-mineshaft-600 bg-mineshaft-800 p-4 drop-shadow">
<div className="mt-4 rounded-sm border border-mineshaft-600 bg-mineshaft-800 p-4 drop-shadow-sm">
<div className="mb-1 ml-2 text-sm text-gray-300">Password should contain:</div>
<div className="ml-2 flex flex-row items-center justify-start">
{passwordErrorTooShort ? (
@@ -45,7 +45,7 @@ export const InputBackupKeyStep = ({ verificationToken, onComplete }: Props) =>
onSubmit={handleSubmit(getEncryptedKeyHandler)}
className="mx-auto flex w-full flex-col items-center justify-center"
>
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Enter your backup key
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
@@ -100,7 +100,7 @@ export const PasswordSetupPage = () => {
<form onSubmit={handleSetPassword}>
<Card className="flex w-full max-w-lg flex-col rounded-md border border-mineshaft-600 px-8 py-4">
<CardTitle
className="p-0 pb-4 pt-2 text-left text-xl"
className="p-0 pt-2 pb-4 text-left text-xl"
subTitle="Make sure to store your password somewhere safe."
>
<div className="flex flex-row items-center">
@@ -37,7 +37,7 @@ export const EmailDuplicationConfirmation = ({ onRemoveDuplicateLater }: Props)
}, [logout, navigate]);
return (
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<Helmet>
<title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -60,15 +60,15 @@ export const EmailDuplicationConfirmation = ({ onRemoveDuplicateLater }: Props)
</Link>
<form className="mx-auto flex w-full flex-col items-center justify-center">
<div className="mb-6">
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-2xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-2xl font-medium text-transparent">
Multiple Accounts Detected
</h1>
<p className="text-md mb-4 text-center text-white">
<span className="text-slate-300">You&apos;re currently logged in as</span>{" "}
<b>{duplicateAccounts?.data?.myAccount?.username}</b>.
</p>
<div className="mb-4 mt-4 flex flex-col rounded-r border-l-2 border-l-primary bg-mineshaft-300/5 px-4 py-2.5">
<p className="mb-2 mt-1 text-sm text-bunker-300">
<div className="mt-4 mb-4 flex flex-col rounded-r border-l-2 border-l-primary bg-mineshaft-300/5 px-4 py-2.5">
<p className="mt-1 mb-2 text-sm text-bunker-300">
We&apos;ve detected multiple accounts using variations of the same email address.
</p>
</div>
@@ -76,7 +76,7 @@ export const EmailDuplicationConfirmation = ({ onRemoveDuplicateLater }: Props)
<div className="mb-4 w-full border-b border-mineshaft-400 pb-1 text-sm text-mineshaft-200">
Your other accounts
</div>
<div className="thin-scrollbar flex h-full max-h-60 w-full flex-col items-stretch gap-2 overflow-auto rounded-md">
<div className="flex h-full max-h-60 thin-scrollbar w-full flex-col items-stretch gap-2 overflow-auto rounded-md">
{duplicateAccounts?.data?.duplicateAccounts?.map((el) => {
const lastSession = el.devices?.at(-1);
return (
@@ -84,7 +84,7 @@ export const EmailDuplicationConfirmation = ({ onRemoveDuplicateLater }: Props)
key={el.id}
className="flex items-center gap-8 rounded-md bg-mineshaft-700 px-4 py-3 text-gray-200"
>
<div className="group flex flex-grow flex-col">
<div className="group flex grow flex-col">
<div className="truncate text-sm transition-colors">{el.username}</div>
<div className="mt-2 text-xs">
Last logged in at {format(new Date(el.updatedAt), "Pp")}
@@ -113,7 +113,7 @@ export const EmailDuplicationConfirmation = ({ onRemoveDuplicateLater }: Props)
<div className="mt-4 flex w-full flex-col">
<div className="flex gap-6">
<Button
className="flex-1 flex-grow"
className="flex-1 grow"
isLoading={removeDuplicateEmails.isPending}
onClick={() => handlePopUpToggle("removeDuplicateConfirm", true)}
>
@@ -122,7 +122,7 @@ export const EmailDuplicationConfirmation = ({ onRemoveDuplicateLater }: Props)
<Button
variant="outline_bg"
onClick={() => onRemoveDuplicateLater()}
className="flex-1 flex-grow"
className="flex-1 grow"
>
Remind me later
</Button>
@@ -254,7 +254,7 @@ export const SelectOrganizationSection = () => {
}
return (
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<Helmet>
<title>{t("common.head-title", { title: t("login.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -284,7 +284,7 @@ export const SelectOrganizationSection = () => {
</Link>
<form className="mx-auto flex w-full flex-col items-center justify-center">
<div className="mb-8 space-y-2">
<h1 className="bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-2xl font-medium text-transparent">
<h1 className="bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-2xl font-medium text-transparent">
Choose your organization
</h1>
<div className="space-y-1">
@@ -293,7 +293,7 @@ export const SelectOrganizationSection = () => {
</p>
<p className="text-md text-center text-gray-500">
Not you?{" "}
<Button variant="link" onClick={handleLogout} className="font-semibold">
<Button variant="link" onClick={handleLogout} className="font-medium">
Change account
</Button>
</p>
@@ -308,7 +308,7 @@ export const SelectOrganizationSection = () => {
<div
onClick={() => handleSelectOrganization(org)}
key={org.id}
className="group flex cursor-pointer items-center justify-between rounded-md bg-mineshaft-700 px-4 py-3 capitalize text-gray-200 shadow-md transition-colors hover:bg-mineshaft-600"
className="group flex cursor-pointer items-center justify-between rounded-md bg-mineshaft-700 px-4 py-3 text-gray-200 capitalize shadow-md transition-colors hover:bg-mineshaft-600"
>
<p className="truncate transition-colors">{org.name}</p>
@@ -138,11 +138,11 @@ export const SignupInvitePage = () => {
// Step 4 of the sign up process (download the emergency kit pdf)
const stepConfirmEmail = (
<div className="h-7/12 mx-1 mb-36 flex w-full max-w-xs flex-col items-center rounded-xl border border-mineshaft-600 bg-mineshaft-800 px-4 py-8 drop-shadow-xl md:mb-16 md:max-w-lg md:px-6">
<p className="mb-2 flex justify-center text-center text-4xl font-semibold text-primary-100">
<div className="mx-1 mb-36 flex h-7/12 w-full max-w-xs flex-col items-center rounded-xl border border-mineshaft-600 bg-mineshaft-800 px-4 py-8 drop-shadow-xl md:mb-16 md:max-w-lg md:px-6">
<p className="mb-2 flex justify-center text-center text-4xl font-medium text-primary-100">
Confirm your email
</p>
<div className="mx-auto mb-2 mt-4 flex max-h-24 max-w-md flex-col items-center justify-center px-4 text-lg md:p-2">
<div className="mx-auto mt-4 mb-2 flex max-h-24 max-w-md flex-col items-center justify-center px-4 text-lg md:p-2">
<Button
onClick={async () => {
try {
@@ -179,8 +179,8 @@ export const SignupInvitePage = () => {
// Because this is the invite signup - we directly go to the last step of signup (email is already verified)
const main = (
<div className="h-7/12 mx-auto mb-32 w-max rounded-xl border border-mineshaft-600 bg-mineshaft-800 px-8 py-10 drop-shadow-xl md:mb-16">
<p className="mx-8 mb-6 flex justify-center bg-gradient-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16">
<div className="mx-auto mb-32 h-7/12 w-max rounded-xl border border-mineshaft-600 bg-mineshaft-800 px-8 py-10 drop-shadow-xl md:mb-16">
<p className="mx-8 mb-6 flex justify-center bg-linear-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16">
Almost there!
</p>
<div className="relative z-0 flex max-h-24 w-full items-center justify-end rounded-lg md:p-2">
@@ -232,7 +232,7 @@ export const SignupInvitePage = () => {
return (
<div className="items-top ml-1 flex flex-row justify-start" key={key}>
<div>
<FontAwesomeIcon icon={faXmark} className="text-md ml-0.5 mr-2.5 text-red" />
<FontAwesomeIcon icon={faXmark} className="text-md mr-2.5 ml-0.5 text-red" />
</div>
<p className="text-sm text-gray-400">{errors[key as keyof Errors]}</p>
</div>
@@ -259,7 +259,7 @@ export const SignupInvitePage = () => {
);
return (
<div className="flex h-screen flex-col items-center justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<div className="flex h-screen flex-col items-center justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
<Helmet>
<title>Sign Up</title>
<link rel="icon" href="/infisical.ico" />
@@ -274,7 +274,7 @@ export const SignupInvitePage = () => {
) : (
<>
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" />
</div>
</Link>
@@ -125,7 +125,7 @@ export const SignUpPage = () => {
};
return (
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex max-h-screen min-h-screen flex-col justify-center overflow-y-auto bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet>
<title>{t("common.head-title", { title: t("signup.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -133,7 +133,7 @@ export const SignUpPage = () => {
<meta property="og:title" content={t("signup.og-title") as string} />
<meta name="og:description" content={t("signup.og-description") as string} />
</Helmet>
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" />
</div>
<form onSubmit={(e) => e.preventDefault()}>{renderView(step)}</form>
@@ -67,7 +67,7 @@ export const SignupSsoPage = () => {
};
return (
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex min-h-screen flex-col justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet>
<title>{t("common.head-title", { title: t("signup.title") })}</title>
<link rel="icon" href="/infisical.ico" />
@@ -75,7 +75,7 @@ export const SignupSsoPage = () => {
<meta property="og:title" content={t("signup.og-title") as string} />
<meta name="og:description" content={t("signup.og-description") as string} />
</Helmet>
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img
src="/images/gradientLogo.svg"
style={{
@@ -149,7 +149,7 @@ export const EmailConfirmationStep = ({
fields={6}
onChange={setCode}
{...props}
className="mb-2 mt-6"
className="mt-6 mb-2"
/>
</div>
<div className="mx-auto mt-4 block w-max md:hidden">
@@ -160,11 +160,11 @@ export const EmailConfirmationStep = ({
fields={6}
onChange={setCode}
{...propsPhone}
className="mb-2 mt-2"
className="mt-2 mb-2"
/>
</div>
{codeError && <Error text="Oops. Your code is wrong. Please try again." />}
<div className="mx-auto mt-2 flex w-1/4 min-w-[20rem] max-w-xs flex-col items-center justify-center text-center text-sm md:max-w-md md:text-left lg:w-[19%]">
<div className="mx-auto mt-2 flex w-1/4 max-w-xs min-w-[20rem] flex-col items-center justify-center text-center text-sm md:max-w-md md:text-left lg:w-[19%]">
<div className="text-l w-full py-1 text-lg">
<Button
type="submit"
@@ -167,7 +167,7 @@ export const UserInfoSSOStep = ({
return (
<div className="mx-auto mb-36 h-full w-max rounded-xl md:mb-16 md:px-8">
<p className="text-medium mx-8 mb-6 flex justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-xl font-bold text-transparent md:mx-16">
<p className="text-medium mx-8 mb-6 flex justify-center bg-linear-to-b from-white to-bunker-200 bg-clip-text text-xl font-bold text-transparent md:mx-16">
{t("signup.step3-message")}
</p>
<div className="mx-auto mb-36 h-full w-max rounded-xl py-6 md:mb-16 md:border md:border-mineshaft-600 md:bg-mineshaft-800 md:px-8">
@@ -184,7 +184,7 @@ export const UserInfoSSOStep = ({
className="h-12"
/>
{nameError && (
<p className="ml-1 mt-1 w-full text-left text-xs text-red-600">
<p className="mt-1 ml-1 w-full text-left text-xs text-red-600">
Please, specify your name
</p>
)}
@@ -204,7 +204,7 @@ export const UserInfoSSOStep = ({
isDisabled={forceDefaultOrg}
/>
{organizationNameError && (
<p className="ml-1 mt-1 w-full text-left text-xs text-red-600">
<p className="mt-1 ml-1 w-full text-left text-xs text-red-600">
Please, specify your organization name
</p>
)}
@@ -223,7 +223,7 @@ export const UserInfoSSOStep = ({
/>
</div>
)}
<div className="mx-auto mt-2 flex w-1/4 min-w-[20rem] max-w-xs flex-col items-center justify-center text-center text-sm md:max-w-md md:text-left lg:w-[19%]">
<div className="mx-auto mt-2 flex w-1/4 max-w-xs min-w-[20rem] flex-col items-center justify-center text-center text-sm md:max-w-md md:text-left lg:w-[19%]">
<div className="text-l w-full py-1 text-lg">
<Button
type="submit"
@@ -43,7 +43,7 @@ export const VerifyEmailPage = () => {
};
return (
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<div className="flex min-h-screen flex-col justify-center bg-linear-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
<Helmet>
<title>Reset Password</title>
<link rel="icon" href="/infisical.ico" />
@@ -55,7 +55,7 @@ export const VerifyEmailPage = () => {
/>
</Helmet>
<Link to="/">
<div className="mb-4 mt-20 flex justify-center">
<div className="mt-20 mb-4 flex justify-center">
<img
src="/images/gradientLogo.svg"
style={{
@@ -71,7 +71,7 @@ export const VerifyEmailPage = () => {
onSubmit={onSubmit}
className="mx-auto flex w-full flex-col items-center justify-center"
>
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Forgot your password?
</h1>
<p className="w-max justify-center text-center text-sm text-gray-400">
@@ -113,7 +113,7 @@ export const VerifyEmailPage = () => {
)}
{step === 2 && (
<div className="mx-auto flex w-full flex-col items-center justify-center">
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
<h1 className="mb-2 bg-linear-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Look for an email in your inbox
</h1>
<p className="w-max max-w-lg justify-center text-center text-sm text-gray-400">
@@ -68,7 +68,7 @@ export const PkiAlertRow = ({ alert, handlePopUpOpen }: Props) => {
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
? "hover:bg-red-500! hover:text-white!"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={(e) => {
@@ -48,7 +48,7 @@ export const PkiAlertsSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Alerts</p>
<p className="text-xl font-medium text-mineshaft-100">Alerts</p>
<ProjectPermissionCan
I={ProjectPermissionActions.Create}
a={ProjectPermissionSub.PkiAlerts}
@@ -48,7 +48,7 @@ export const PkiCollectionSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Certificate Collections</p>
<p className="text-xl font-medium text-mineshaft-100">Certificate Collections</p>
<ProjectPermissionCan
I={ProjectPermissionActions.Create}
a={ProjectPermissionSub.PkiCollections}
@@ -107,7 +107,7 @@ export const PkiCollectionTable = ({ handlePopUpOpen }: Props) => {
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
? "hover:bg-red-500! hover:text-white!"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={(e) => {
@@ -105,7 +105,7 @@ const Page = () => {
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
? "hover:bg-red-500! hover:text-white!"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={() => handlePopUpOpen("deleteCa")}
@@ -8,7 +8,7 @@ export const CaCertificatesSection = ({ caId }: Props) => {
return (
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">CA Certificates</h3>
<h3 className="text-lg font-medium text-mineshaft-100">CA Certificates</h3>
{/* <IconButton
ariaLabel="copy icon"
variant="plain"
@@ -8,7 +8,7 @@ export const CaCrlsSection = ({ caId }: Props) => {
return (
<div className="mt-4 w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">
<h3 className="text-lg font-medium text-mineshaft-100">
CA Certificate Revocation Lists (CRLs)
</h3>
</div>
@@ -40,7 +40,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
return ca ? (
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">CA Details</h3>
<h3 className="text-lg font-medium text-mineshaft-100">CA Details</h3>
<ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Identity}>
{(isAllowed) => {
return (
@@ -66,11 +66,11 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
</div>
<div className="pt-4">
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">CA Type</p>
<p className="text-sm font-medium text-mineshaft-300">CA Type</p>
<p className="text-sm text-mineshaft-300">{caTypeToNameMap[ca.configuration.type]}</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">CA ID</p>
<p className="text-sm font-medium text-mineshaft-300">CA ID</p>
<div className="group flex align-top">
<p className="text-sm text-mineshaft-300">{ca.id}</p>
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
@@ -93,7 +93,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
{ca.configuration.type === InternalCaType.INTERMEDIATE &&
ca.status !== CaStatus.PENDING_CERTIFICATE && (
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Parent CA ID</p>
<p className="text-sm font-medium text-mineshaft-300">Parent CA ID</p>
<div className="group flex align-top">
<p className="text-sm text-mineshaft-300">
{ca.configuration.parentCaId
@@ -121,25 +121,25 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
</div>
)}
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
<p className="text-sm font-medium text-mineshaft-300">Name</p>
<p className="text-sm text-mineshaft-300">{ca.name}</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Status</p>
<p className="text-sm font-medium text-mineshaft-300">Status</p>
<p className="text-sm text-mineshaft-300">{caStatusToNameMap[ca.status]}</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Key Algorithm</p>
<p className="text-sm font-medium text-mineshaft-300">Key Algorithm</p>
<p className="text-sm text-mineshaft-300">
{certKeyAlgorithmToNameMap[ca.configuration.keyAlgorithm]}
</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Max Path Length</p>
<p className="text-sm font-medium text-mineshaft-300">Max Path Length</p>
<p className="text-sm text-mineshaft-300">{ca.configuration.maxPathLength ?? "-"}</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Not Before</p>
<p className="text-sm font-medium text-mineshaft-300">Not Before</p>
<p className="text-sm text-mineshaft-300">
{ca.configuration.notBefore
? format(new Date(ca.configuration.notBefore), "yyyy-MM-dd")
@@ -147,7 +147,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Not After</p>
<p className="text-sm font-medium text-mineshaft-300">Not After</p>
<p className="text-sm text-mineshaft-300">
{ca.configuration.notAfter
? format(new Date(ca.configuration.notAfter), "yyyy-MM-dd")
@@ -155,7 +155,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Enable Direct Issuance</p>
<p className="text-sm font-medium text-mineshaft-300">Enable Direct Issuance</p>
<p className="text-sm text-mineshaft-300">{ca.enableDirectIssuance ? "True" : "False"}</p>
</div>
{ca.status === CaStatus.ACTIVE && (
@@ -113,7 +113,7 @@ export const ExternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
</div>
</div>
<div className="mb-8 flex items-center justify-between rounded-md bg-white/[0.07] p-2 text-base text-gray-400">
<p className="mr-4 whitespace-pre-wrap break-all">{csr}</p>
<p className="mr-4 break-all whitespace-pre-wrap">{csr}</p>
</div>
</>
)}
@@ -72,7 +72,7 @@ export const CaSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Internal Certificate Authorities</p>
<p className="text-xl font-medium text-mineshaft-100">Internal Certificate Authorities</p>
<ProjectPermissionCan
I={ProjectPermissionActions.Create}
a={ProjectPermissionSub.CertificateAuthorities}
@@ -76,7 +76,7 @@ export const ExternalCaSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">External Certificate Authorities</p>
<p className="text-xl font-medium text-mineshaft-100">External Certificate Authorities</p>
<ProjectPermissionCan
I={ProjectPermissionActions.Create}
a={ProjectPermissionSub.CertificateAuthorities}
@@ -92,7 +92,7 @@ export const CertificateContent = ({
</div>
</div>
<div className="mb-8 flex items-center justify-between rounded-md bg-white/[0.07] p-2 text-base text-gray-400">
<p className="mr-4 whitespace-pre-wrap break-all">{certificate}</p>
<p className="mr-4 break-all whitespace-pre-wrap">{certificate}</p>
</div>
{certificateChain && (
<>
@@ -127,7 +127,7 @@ export const CertificateContent = ({
</div>
</div>
<div className="mb-8 flex items-center justify-between rounded-md bg-white/[0.07] p-2 text-base text-gray-400">
<p className="mr-4 whitespace-pre-wrap break-all">{certificateChain}</p>
<p className="mr-4 break-all whitespace-pre-wrap">{certificateChain}</p>
</div>
</>
)}
@@ -164,7 +164,7 @@ export const CertificateContent = ({
</div>
</div>
<div className="mb-8 flex items-center justify-between rounded-md bg-white/[0.07] p-2 text-base text-gray-400">
<p className="mr-4 whitespace-pre-wrap break-all">{privateKey}</p>
<p className="mr-4 break-all whitespace-pre-wrap">{privateKey}</p>
</div>
</>
)}
@@ -440,7 +440,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -474,7 +474,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{EXTENDED_KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -198,7 +198,7 @@ export const CertificateTemplateEnrollmentModal = ({ popUp, handlePopUpToggle }:
<TextArea
{...field}
isDisabled={disableBootstrapCertValidation}
className="min-h-[15rem] border-none bg-mineshaft-900 text-gray-400"
className="min-h-60 border-none bg-mineshaft-900 text-gray-400"
reSize="none"
/>
</FormControl>
@@ -399,7 +399,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -432,7 +432,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{EXTENDED_KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -65,7 +65,7 @@ export const CertificateTemplatesSection = ({ caId }: Props) => {
return (
<div className="mt-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">Certificate Templates</h3>
<h3 className="text-lg font-medium text-mineshaft-100">Certificate Templates</h3>
<ProjectPermissionCan
I={ProjectPermissionPkiTemplateActions.Create}
a={ProjectPermissionSub.CertificateTemplates}
@@ -60,7 +60,7 @@ export const CertificatesSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Certificates</p>
<p className="text-xl font-medium text-mineshaft-100">Certificates</p>
<ProjectPermissionCan
I={ProjectPermissionCertificateActions.Create}
a={ProjectPermissionSub.Certificates}
@@ -42,7 +42,7 @@ export const IntegrationsListPage = () => {
<meta property="og:title" content="Manage your certificates in seconds" />
<meta name="og:description" content="Sync and manage PKI certificates across services" />
</Helmet>
<div className="container relative mx-auto max-w-7xl pb-12 text-white">
<div className="relative container mx-auto max-w-7xl pb-12 text-white">
<div className="mb-8">
<PageHeader
title="Integrations"
@@ -143,10 +143,10 @@ export const PkiSyncRow = ({
<img
alt={`${destinationDetails.name} sync`}
src={`/images/integrations/${destinationDetails.image}`}
className="min-w-[1.75rem]"
className="min-w-7"
/>
</Td>
<Td className="!min-w-[8rem] max-w-0">
<Td className="max-w-0 min-w-32!">
<div>
<div className="flex w-full items-center">
<p className="truncate">{name}</p>
@@ -192,7 +192,7 @@ export const PkiSyncRow = ({
className="max-w-sm"
content={
[PkiSyncStatus.Succeeded, PkiSyncStatus.Failed].includes(syncStatus) ? (
<div className="flex flex-col gap-2 whitespace-normal py-1">
<div className="flex flex-col gap-2 py-1 whitespace-normal">
{lastSyncedAt && (
<div>
<div
@@ -200,11 +200,11 @@ export const PkiSyncRow = ({
>
<FontAwesomeIcon
icon={faCalendarCheck}
className="ml-1 pr-1.5 pt-0.5 text-sm"
className="ml-1 pt-0.5 pr-1.5 text-sm"
/>
<div className="text-xs">Last Synced</div>
</div>
<div className="rounded bg-mineshaft-600 p-2 text-xs">
<div className="rounded-sm bg-mineshaft-600 p-2 text-xs">
{format(new Date(lastSyncedAt), "yyyy-MM-dd, hh:mm aaa")}
</div>
</div>
@@ -212,10 +212,10 @@ export const PkiSyncRow = ({
{failureMessage && (
<div>
<div className="mb-2 flex self-start text-red">
<FontAwesomeIcon icon={faXmark} className="ml-1 pr-1.5 pt-0.5 text-sm" />
<FontAwesomeIcon icon={faXmark} className="ml-1 pt-0.5 pr-1.5 text-sm" />
<div className="text-xs">Failure Reason</div>
</div>
<div className="break-words rounded bg-mineshaft-600 p-2 text-xs">
<div className="rounded-sm bg-mineshaft-600 p-2 text-xs break-words">
{failureMessage}
</div>
</div>
@@ -235,7 +235,7 @@ export const PkiSyncRow = ({
content="Auto-Sync is disabled. Certificate changes in the PKI subscriber will not be automatically synced to the destination."
>
<div>
<Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap bg-mineshaft-400/50 text-bunker-300">
<Badge className="flex h-5 w-min items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300">
<FontAwesomeIcon icon={faBan} />
{!syncStatus && "Auto-Sync Disabled"}
</Badge>
@@ -23,7 +23,7 @@ export const PkiSyncTableCell = ({
secondaryClassName
}: PkiSyncTableCellProps) => {
return (
<Td className="!min-w-[8rem] max-w-0">
<Td className="max-w-0 min-w-32!">
<Tooltip
side="left"
className="max-w-2xl break-words"
@@ -292,7 +292,7 @@ export const PkiSyncsTable = ({ pkiSyncs }: Props) => {
<FontAwesomeIcon icon={faFilter} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent className="thin-scrollbar max-h-[70vh] overflow-y-auto" align="end">
<DropdownMenuContent className="max-h-[70vh] thin-scrollbar overflow-y-auto" align="end">
<DropdownMenuLabel>Status</DropdownMenuLabel>
{[PkiSyncStatus.Running, PkiSyncStatus.Succeeded, PkiSyncStatus.Failed].map(
(status) => (
@@ -409,7 +409,7 @@ export const PkiSyncsTable = ({ pkiSyncs }: Props) => {
</IconButton>
</div>
</Th>
<Th className="min-w-[10.5rem]">
<Th className="min-w-42">
<div className="flex items-center">
Status
<IconButton
@@ -64,13 +64,13 @@ export const PkiSyncsTab = () => {
<div className="mb-4 flex items-center justify-between">
<div>
<div className="flex items-start gap-1">
<p className="text-xl font-semibold text-mineshaft-100">Certificate Syncs</p>
<p className="text-xl font-medium text-mineshaft-100">Certificate Syncs</p>
<a
href="https://infisical.com/docs/integrations/pki-syncs/overview"
target="_blank"
rel="noopener noreferrer"
>
<div className="ml-1 mt-[0.32rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<div className="mt-[0.32rem] ml-1 inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
@@ -111,7 +111,7 @@ export const PkiCollectionPage = () => {
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
? "hover:bg-red-500! hover:text-white!"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={() =>
@@ -23,7 +23,7 @@ export const PkiCollectionDetailsSection = ({ collectionId, handlePopUpOpen }: P
return pkiCollection ? (
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">Collection Details</h3>
<h3 className="text-lg font-medium text-mineshaft-100">Collection Details</h3>
<ProjectPermissionCan
I={ProjectPermissionActions.Edit}
a={ProjectPermissionSub.PkiCollections}
@@ -51,7 +51,7 @@ export const PkiCollectionDetailsSection = ({ collectionId, handlePopUpOpen }: P
</div>
<div className="pt-4">
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">PKI Collection ID</p>
<p className="text-sm font-medium text-mineshaft-300">PKI Collection ID</p>
<div className="group flex align-top">
<p className="text-sm text-mineshaft-300">{pkiCollection.id}</p>
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
@@ -72,11 +72,11 @@ export const PkiCollectionDetailsSection = ({ collectionId, handlePopUpOpen }: P
</div>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
<p className="text-sm font-medium text-mineshaft-300">Name</p>
<p className="text-sm text-mineshaft-300">{pkiCollection.name}</p>
</div>
<div>
<p className="text-sm font-semibold text-mineshaft-300">Description</p>
<p className="text-sm font-medium text-mineshaft-300">Description</p>
<p className="text-sm text-mineshaft-300">{pkiCollection.description}</p>
</div>
</div>
@@ -47,7 +47,7 @@ export const PkiCollectionItemsSection = ({ collectionId, type }: Props) => {
return pkiCollection ? (
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">{sectionName}</h3>
<h3 className="text-lg font-medium text-mineshaft-100">{sectionName}</h3>
<IconButton
ariaLabel="copy icon"
variant="plain"
@@ -96,7 +96,7 @@ const Page = () => {
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
? "hover:bg-red-500! hover:text-white!"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={() =>
@@ -13,7 +13,7 @@ export const PkiSubscriberCertificatesSection = ({ subscriberName }: Props) => {
return (
<div className="h-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">Certificates</h3>
<h3 className="text-lg font-medium text-mineshaft-100">Certificates</h3>
</div>
<div className="py-4">
<PkiSubscriberCertificatesTable
@@ -114,7 +114,7 @@ export const PkiSubscriberDetailsSection = ({ subscriberName, handlePopUpOpen }:
return pkiSubscriber ? (
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">PKI Subscriber Details</h3>
<h3 className="text-lg font-medium text-mineshaft-100">PKI Subscriber Details</h3>
<ProjectPermissionCan
I={ProjectPermissionPkiSubscriberActions.Edit}
a={ProjectPermissionSub.PkiSubscribers}
@@ -143,7 +143,7 @@ export const PkiSubscriberDetailsSection = ({ subscriberName, handlePopUpOpen }:
</div>
<div className="pt-4">
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">PKI Subscriber ID</p>
<p className="text-sm font-medium text-mineshaft-300">PKI Subscriber ID</p>
<div className="group flex align-top">
<p className="text-sm text-mineshaft-300">{pkiSubscriber.id}</p>
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
@@ -164,22 +164,22 @@ export const PkiSubscriberDetailsSection = ({ subscriberName, handlePopUpOpen }:
</div>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
<p className="text-sm font-medium text-mineshaft-300">Name</p>
<p className="text-sm text-mineshaft-300">{pkiSubscriber.name}</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Status</p>
<p className="text-sm font-medium text-mineshaft-300">Status</p>
<p className="text-sm text-mineshaft-300">
{pkiSubscriberStatusToNameMap[pkiSubscriber.status]}
</p>
</div>
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Common Name</p>
<p className="text-sm font-medium text-mineshaft-300">Common Name</p>
<p className="text-sm text-mineshaft-300">{pkiSubscriber.commonName}</p>
</div>
{pkiSubscriber.lastOperationAt && (
<div className="mb-4">
<p className="text-sm font-semibold text-mineshaft-300">Last Operation (Local Time)</p>
<p className="text-sm font-medium text-mineshaft-300">Last Operation (Local Time)</p>
<p className="text-sm text-mineshaft-300">
{new Date(pkiSubscriber.lastOperationAt).toLocaleString()}
</p>
@@ -188,7 +188,7 @@ export const PkiSubscriberDetailsSection = ({ subscriberName, handlePopUpOpen }:
{pkiSubscriber.lastOperationStatus === SubscriberOperationStatus.FAILED && (
<div className="mb-4">
<GenericFieldLabel labelClassName="text-red" label="Last Operation Status">
<p className="break-words rounded bg-mineshaft-600 p-2 text-xs">
<p className="rounded-sm bg-mineshaft-600 p-2 text-xs break-words">
{pkiSubscriber.lastOperationMessage}
</p>
</GenericFieldLabel>
@@ -655,7 +655,7 @@ export const PkiSubscriberModal = ({ popUp, handlePopUpToggle }: Props) => {
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -688,7 +688,7 @@ export const PkiSubscriberModal = ({ popUp, handlePopUpToggle }: Props) => {
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{EXTENDED_KEY_USAGES_OPTIONS.map(
({ label, value: optionValue }) => {
return (
@@ -87,7 +87,7 @@ export const PkiSubscriberSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Subscribers</p>
<p className="text-xl font-medium text-mineshaft-100">Subscribers</p>
<div className="flex w-full justify-end">
<a
target="_blank"
@@ -92,10 +92,10 @@ const PageContent = () => {
<img
alt={`${destinationDetails.name} sync`}
src={`/images/integrations/${destinationDetails.image}`}
className="ml-1 mt-3 w-16"
className="mt-3 ml-1 w-16"
/>
<div>
<p className="text-3xl font-semibold text-white">{pkiSync.name}</p>
<p className="text-3xl font-medium text-white">{pkiSync.name}</p>
<p className="leading-3 text-bunker-300">{destinationDetails.name} PKI Sync</p>
</div>
<PkiSyncActionTriggers pkiSync={pkiSync} />
@@ -132,7 +132,7 @@ export const PkiSyncActionTriggers = ({ pkiSync }: Props) => {
return (
<>
<div className="ml-auto mt-4 flex flex-wrap items-center justify-end gap-2">
<div className="mt-4 ml-auto flex flex-wrap items-center justify-end gap-2">
{syncOption?.canImportCertificates && <PkiSyncImportStatusBadge pkiSync={pkiSync} />}
<PkiSyncRemoveStatusBadge pkiSync={pkiSync} />
{pkiSync.isAutoSyncEnabled ? (
@@ -149,7 +149,7 @@ export const PkiSyncActionTriggers = ({ pkiSync }: Props) => {
content="Auto-Sync is disabled. Certificate changes in the PKI subscriber will not be automatically synced to the destination."
>
<div>
<Badge className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap bg-mineshaft-400/50 text-bunker-300">
<Badge className="flex h-5 w-min items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Auto-Sync Disabled</span>
</Badge>
@@ -26,7 +26,7 @@ export const PkiSyncAuditLogsSection = ({ pkiSync }: Props) => {
return (
<div className="flex max-h-full w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
<h3 className="font-semibold text-mineshaft-100">Sync Logs</h3>
<h3 className="font-medium text-mineshaft-100">Sync Logs</h3>
{subscription.auditLogs && (
<p className="text-xs text-bunker-300">
Displaying audit logs from the last {Math.min(auditLogsRetentionDays, 60)} days
@@ -47,7 +47,7 @@ export const PkiSyncDestinationSection = ({ pkiSync, onEditDestination }: Props)
return (
<div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
<h3 className="font-semibold text-mineshaft-100">Destination Configuration</h3>
<h3 className="font-medium text-mineshaft-100">Destination Configuration</h3>
<ProjectPermissionCan I={ProjectPermissionPkiSyncActions.Edit} a={permissionSubject}>
{(isAllowed) => (
<IconButton
@@ -57,7 +57,7 @@ export const PkiSyncDetailsSection = ({ pkiSync, onEditDetails }: Props) => {
return (
<div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
<h3 className="font-semibold text-mineshaft-100">Details</h3>
<h3 className="font-medium text-mineshaft-100">Details</h3>
<ProjectPermissionCan I={ProjectPermissionPkiSyncActions.Edit} a={permissionSubject}>
{(isAllowed) => (
<IconButton
@@ -91,7 +91,9 @@ export const PkiSyncDetailsSection = ({ pkiSync, onEditDetails }: Props) => {
)}
{syncStatus === PkiSyncStatus.Failed && failureMessage && (
<GenericFieldLabel labelClassName="text-red" label="Last Sync Error">
<p className="break-words rounded bg-mineshaft-600 p-2 text-xs">{failureMessage}</p>
<p className="rounded-sm bg-mineshaft-600 p-2 text-xs break-words">
{failureMessage}
</p>
</GenericFieldLabel>
)}
</div>
@@ -27,7 +27,7 @@ export const PkiSyncOptionsSection = ({ pkiSync, onEditOptions }: Props) => {
<div>
<div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
<h3 className="font-semibold text-mineshaft-100">Sync Options</h3>
<h3 className="font-medium text-mineshaft-100">Sync Options</h3>
<ProjectPermissionCan I={ProjectPermissionPkiSyncActions.Edit} a={permissionSubject}>
{(isAllowed) => (
<IconButton
@@ -32,7 +32,7 @@ export const PkiSyncSourceSection = ({ pkiSync, onEditSource }: Props) => {
<div>
<div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
<h3 className="font-semibold text-mineshaft-100">Source</h3>
<h3 className="font-medium text-mineshaft-100">Source</h3>
<div>
{!subscriberId && (
<Tooltip content="The PKI subscriber for this sync has been deleted. Configure a new source or remove this sync.">
@@ -113,7 +113,7 @@ export const PkiTemplateListPage = () => {
</div>
<div className="container mx-auto mb-6 max-w-7xl rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Templates</p>
<p className="text-xl font-medium text-mineshaft-100">Templates</p>
<div className="flex w-full justify-end">
<ProjectPermissionCan
I={ProjectPermissionPkiTemplateActions.Create}
@@ -327,7 +327,7 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -360,7 +360,7 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
errorText={error?.message}
isError={Boolean(error)}
>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{EXTENDED_KEY_USAGES_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -129,7 +129,7 @@ const KmipClientForm = ({ onComplete, kmipClient }: FormProps) => {
isError={Boolean(errors.description?.message)}
>
<TextArea
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
{...register("description")}
/>
</FormControl>
@@ -139,7 +139,7 @@ const KmipClientForm = ({ onComplete, kmipClient }: FormProps) => {
render={({ field: { onChange, value }, fieldState: { error } }) => {
return (
<FormControl label="Permissions" errorText={error?.message} isError={Boolean(error)}>
<div className="mb-7 mt-2 grid grid-cols-2 gap-2">
<div className="mt-2 mb-7 grid grid-cols-2 gap-2">
{KMIP_PERMISSIONS_OPTIONS.map(({ label, value: optionValue }) => {
return (
<Checkbox
@@ -143,7 +143,7 @@ export const KmipClientTable = () => {
>
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<p className="whitespace-nowrap text-xl font-semibold text-mineshaft-100">KMIP Clients</p>
<p className="text-xl font-medium whitespace-nowrap text-mineshaft-100">KMIP Clients</p>
<div className="flex w-full justify-end pr-4">
<a
target="_blank"
@@ -89,7 +89,7 @@ const DecryptForm = ({ cmek }: FormProps) => {
{plaintext ? (
<FormControl label="Decrypted Data (plaintext)">
<TextArea
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
isDisabled
value={plaintext}
/>
@@ -102,7 +102,7 @@ const DecryptForm = ({ cmek }: FormProps) => {
>
<TextArea
{...register("ciphertext")}
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
/>
</FormControl>
)}
@@ -81,7 +81,7 @@ const EncryptForm = ({ cmek }: FormProps) => {
{ciphertext ? (
<FormControl label="Encrypted Data (Ciphertext)">
<TextArea
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
isDisabled
value={cmekEncrypt.data?.ciphertext}
/>
@@ -95,7 +95,7 @@ const EncryptForm = ({ cmek }: FormProps) => {
>
<TextArea
{...register("plaintext")}
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
/>
</FormControl>
<Controller
@@ -211,7 +211,7 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
isError={Boolean(errors.description?.message)}
>
<TextArea
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
{...register("description")}
/>
</FormControl>
@@ -93,7 +93,7 @@ const SignForm = ({ cmek }: FormProps) => {
{signature ? (
<FormControl label="Data Signature">
<TextArea
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
isDisabled
value={signature}
/>
@@ -105,10 +105,7 @@ const SignForm = ({ cmek }: FormProps) => {
errorText={errors.data?.message}
isError={Boolean(errors.data)}
>
<TextArea
{...register("data")}
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
/>
<TextArea {...register("data")} className="max-h-80 min-h-40 max-w-full min-w-full" />
</FormControl>
<div className="mb-6 flex w-full items-center justify-between gap-2">
@@ -216,7 +216,7 @@ export const CmekTable = () => {
>
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<p className="whitespace-nowrap text-xl font-semibold text-mineshaft-100">Keys</p>
<p className="text-xl font-medium whitespace-nowrap text-mineshaft-100">Keys</p>
<div className="flex w-full justify-end pr-4">
<a
target="_blank"
@@ -139,7 +139,7 @@ const VerifyForm = ({ cmek }: FormProps) => {
</div>
<div className="mt-3">
<span className="text-sm opacity-60">Signature:</span>{" "}
<div className="whitespace-pre-wrap break-words rounded-md border border-mineshaft-700 bg-mineshaft-900 p-2 text-sm">
<div className="rounded-md border border-mineshaft-700 bg-mineshaft-900 p-2 text-sm break-words whitespace-pre-wrap">
{signature}
</div>
</div>
@@ -157,10 +157,7 @@ const VerifyForm = ({ cmek }: FormProps) => {
errorText={errors.data?.message}
isError={Boolean(errors.data)}
>
<TextArea
{...register("data")}
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
/>
<TextArea {...register("data")} className="max-h-80 min-h-40 max-w-full min-w-full" />
</FormControl>
<FormControl
@@ -171,7 +168,7 @@ const VerifyForm = ({ cmek }: FormProps) => {
>
<TextArea
{...register("signature")}
className="max-h-[20rem] min-h-[10rem] min-w-full max-w-full"
className="max-h-80 min-h-40 max-w-full min-w-full"
/>
</FormControl>
@@ -51,7 +51,7 @@ export const AuthConsentWrapper = () => {
return (
<>
{config.authConsentContent && !hasConsented && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-mineshaft-700/80 bg-opacity-90">
<div className="bg-opacity-90 fixed inset-0 z-50 flex items-center justify-center bg-mineshaft-700/80">
<div className="max-h-[80vh] w-4/12 overflow-y-auto rounded-lg bg-bunker-800 p-6 text-white">
<ReactMarkdown rehypePlugins={[rehypeRaw]}>
{DOMPurify.sanitize(config.authConsentContent)}
@@ -86,12 +86,12 @@ export const AccessManagementPage = () => {
description="Manage fine-grained access for users, groups, roles, and identities within your organization resources."
/>
{!currentOrg.shouldUseNewPrivilegeSystem && (
<div className="mb-4 mt-4 flex flex-col rounded-r border-l-2 border-l-primary bg-mineshaft-300/5 px-4 py-2.5">
<div className="mt-4 mb-4 flex flex-col rounded-r border-l-2 border-l-primary bg-mineshaft-300/5 px-4 py-2.5">
<div className="mb-1 flex items-center text-sm">
<FontAwesomeIcon icon={faInfoCircle} size="sm" className="mr-1.5 text-primary" />
Your organization is using legacy privilege management
</div>
<p className="mb-2 mt-1 text-sm text-bunker-300">
<p className="mt-1 mb-2 text-sm text-bunker-300">
We&apos;ve developed an improved privilege management system to better serve your
security needs. Upgrade to our new permission-based approach that allows you to
explicitly designate who can modify specific access levels, rather than relying on
@@ -57,7 +57,7 @@ export const OrgGroupsSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Groups</p>
<p className="text-xl font-medium text-mineshaft-100">Groups</p>
<OrgPermissionCan I={OrgPermissionGroupActions.Create} a={OrgPermissionSubjects.Groups}>
{(isAllowed) => (
<Button
@@ -264,7 +264,7 @@ export const IdentityAliCloudAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -1,6 +1,7 @@
import {
faArrowDown,
faArrowUp,
faBan,
faEdit,
faEllipsisV,
faEye,
@@ -30,7 +31,7 @@ import {
THead,
Tr
} from "@app/components/v2";
import { OrgPermissionSubjects, useOrganization } from "@app/context";
import { OrgPermissionSubjects, useOrganization, useSubscription } from "@app/context";
import { OrgPermissionMachineIdentityAuthTemplateActions } from "@app/context/OrgPermissionContext/types";
import {
getUserTablePreference,
@@ -86,12 +87,14 @@ export const IdentityAuthTemplatesTable = ({ handlePopUpOpen }: Props) => {
};
const organizationId = currentOrg?.id || "";
const { subscription } = useSubscription();
const { data, isPending, isFetching } = useGetIdentityAuthTemplates({
organizationId,
limit,
offset,
search: debouncedSearch
search: debouncedSearch,
isDisabled: !subscription.machineIdentityAuthTemplates
});
const { templates = [], totalCount = 0 } = data ?? {};
@@ -172,7 +175,10 @@ export const IdentityAuthTemplatesTable = ({ handlePopUpOpen }: Props) => {
</Tr>
</THead>
<TBody>
{isPending && <TableSkeleton columns={4} innerKey="identity-auth-templates" />}
{subscription.machineIdentityAuthTemplates && isPending && (
<TableSkeleton columns={4} innerKey="identity-auth-templates" />
)}
{!isPending &&
templates?.map((template) => (
<Tr
@@ -265,6 +271,9 @@ export const IdentityAuthTemplatesTable = ({ handlePopUpOpen }: Props) => {
onChangePerPage={handlePerPageChange}
/>
)}
{!subscription.machineIdentityAuthTemplates && (
<EmptyState title="This feature has not been activated for your license." icon={faBan} />
)}
{!isPending && templates.length === 0 && (
<EmptyState
title={
@@ -302,7 +302,7 @@ export const IdentityAwsAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -298,7 +298,7 @@ export const IdentityAzureAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -337,7 +337,7 @@ export const IdentityGcpAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -368,7 +368,7 @@ export const IdentityJwtAuthForm = ({
name={`publicKeys.${index}.value`}
render={({ field, fieldState: { error } }) => (
<FormControl
className="flex-grow"
className="grow"
label={`Public Key ${index + 1}`}
errorText={error?.message}
isError={Boolean(error)}
@@ -482,7 +482,7 @@ export const IdentityJwtAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Claims" : undefined}
icon={
index === 0 ? (
@@ -512,7 +512,7 @@ export const IdentityJwtAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
isError={Boolean(error)}
errorText={error?.message}
>
@@ -606,7 +606,7 @@ export const IdentityJwtAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -547,7 +547,7 @@ export const IdentityKubernetesAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -632,7 +632,7 @@ export const IdentityLdapAuthForm = ({
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={isFirstField ? "Required Attributes" : undefined}
icon={
isFirstField ? (
@@ -689,7 +689,7 @@ export const IdentityLdapAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
isError={Boolean(error)}
errorText={error?.message}
>
@@ -817,7 +817,7 @@ export const IdentityLdapAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -75,7 +75,6 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
control,
name: "metadata"
});
useEffect(() => {
const identity = popUp?.identity?.data as {
identityId: string;
@@ -234,7 +233,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl errorText={error?.message} isError={Boolean(error)}>
<Switch
className="ml-0 mr-2 bg-mineshaft-400/80 shadow-inner data-[state=checked]:bg-green/80"
className="mr-2 ml-0 bg-mineshaft-400/80 shadow-inner data-[state=checked]:bg-green/80"
containerClassName="flex-row-reverse w-fit"
id="delete-protection-enabled"
thumbClassName="bg-mineshaft-800"
@@ -252,7 +251,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
<div className="mb-3 flex flex-col space-y-2">
{metadataFormFields.fields.map(({ id: metadataFieldId }, i) => (
<div key={metadataFieldId} className="flex items-end space-x-2">
<div className="flex-grow">
<div className="grow">
{i === 0 && <span className="text-xs text-mineshaft-400">Key</span>}
<Controller
control={control}
@@ -268,7 +267,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
)}
/>
</div>
<div className="flex-grow">
<div className="grow">
{i === 0 && (
<FormLabel label="Value" className="text-xs text-mineshaft-400" isOptional />
)}
@@ -284,7 +284,7 @@ export const IdentityOciAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -364,7 +364,7 @@ export const IdentityOidcAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Claims" : undefined}
icon={
index === 0 ? (
@@ -394,7 +394,7 @@ export const IdentityOidcAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
isError={Boolean(error)}
errorText={error?.message}
>
@@ -502,7 +502,7 @@ export const IdentityOidcAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Token Claim Mapping" : undefined}
icon={
index === 0 ? (
@@ -543,7 +543,7 @@ export const IdentityOidcAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
isError={Boolean(error)}
errorText={error?.message}
>
@@ -593,7 +593,7 @@ export const IdentityOidcAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
@@ -107,13 +107,13 @@ export const IdentitySection = withPermission(
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-1">
<p className="text-xl font-semibold text-mineshaft-100">Identities</p>
<p className="text-xl font-medium text-mineshaft-100">Identities</p>
<a
href="https://infisical.com/docs/documentation/platform/identities/overview"
target="_blank"
rel="noopener noreferrer"
>
<div className="ml-1 mt-[0.16rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<div className="mt-[0.16rem] ml-1 inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
@@ -155,13 +155,13 @@ export const IdentitySection = withPermission(
<div className="mt-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-1">
<p className="text-xl font-semibold text-mineshaft-100">Identity Auth Templates</p>
<p className="text-xl font-medium text-mineshaft-100">Identity Auth Templates</p>
<a
href="https://infisical.com/docs/documentation/platform/identities/auth-templates"
target="_blank"
rel="noopener noreferrer"
>
<div className="ml-1 mt-[0.16rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<div className="mt-[0.16rem] ml-1 inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
@@ -192,7 +192,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
variant="plain"
size="sm"
className={twMerge(
"flex h-[2.375rem] w-[2.6rem] items-center justify-center overflow-hidden border border-mineshaft-600 bg-mineshaft-800 p-0 transition-all hover:border-primary/60 hover:bg-primary/10",
"flex h-9.5 w-[2.6rem] items-center justify-center overflow-hidden border border-mineshaft-600 bg-mineshaft-800 p-0 transition-all hover:border-primary/60 hover:bg-primary/10",
isTableFiltered && "border-primary/50 text-primary"
)}
>
@@ -208,7 +208,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
>
Roles
</DropdownSubMenuTrigger>
<DropdownSubMenuContent className="thin-scrollbar max-h-[20rem] overflow-y-auto rounded-l-none">
<DropdownSubMenuContent className="max-h-80 thin-scrollbar overflow-y-auto rounded-l-none">
<DropdownMenuLabel className="sticky top-0 bg-mineshaft-900">
Apply Roles to Filter Identities
</DropdownMenuLabel>
@@ -317,7 +317,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
{name}
{lastLoginAuthMethod && lastLoginTime && (
<Tooltip
className="min-w-52 max-w-96 px-3"
className="max-w-96 min-w-52 px-3"
content={
<LastLoginSection
lastLoginAuthMethod={identityAuthToNameMap[lastLoginAuthMethod]}
@@ -272,7 +272,7 @@ export const IdentityTlsCertAuthForm = ({
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
className="mb-0 grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}

Some files were not shown because too many files have changed in this diff Show More