mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-20 18:00:54 +00:00
Merge branch 'main' into ENG-3802
This commit is contained in:
@@ -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>
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+93
-75
@@ -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'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'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'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'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'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={{
|
||||
|
||||
+3
-3
@@ -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"
|
||||
|
||||
+4
-4
@@ -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")}
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+11
-11
@@ -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 && (
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
@@ -54,7 +54,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"
|
||||
|
||||
+8
-8
@@ -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>
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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={() =>
|
||||
|
||||
+4
-4
@@ -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>
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
+1
-1
@@ -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={() =>
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+7
-7
@@ -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>
|
||||
|
||||
+2
-2
@@ -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 (
|
||||
|
||||
+1
-1
@@ -85,7 +85,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} />
|
||||
|
||||
+2
-2
@@ -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>
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+4
-2
@@ -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>
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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.">
|
||||
|
||||
@@ -112,7 +112,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'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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+12
-3
@@ -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={
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+4
-4
@@ -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}
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+3
-3
@@ -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}
|
||||
|
||||
+3
-4
@@ -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 />
|
||||
)}
|
||||
|
||||
+1
-1
@@ -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}
|
||||
|
||||
+5
-5
@@ -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}
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
+3
-3
@@ -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]}
|
||||
|
||||
+1
-1
@@ -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
Reference in New Issue
Block a user