mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 17:30:06 +00:00
feat(infisical-pg): changed frontend api types _id to normal id
This commit is contained in:
@@ -28,7 +28,7 @@ export const LogsFilter = ({ control, reset }: Props) => {
|
||||
const [isEndDatePickerOpen, setIsEndDatePickerOpen] = useState(false);
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { data, isLoading } = useGetAuditLogActorFilterOpts(currentWorkspace?._id ?? "");
|
||||
const { data, isLoading } = useGetAuditLogActorFilterOpts(currentWorkspace?.id ?? "");
|
||||
|
||||
const renderActorSelectItem = (actor: Actor) => {
|
||||
switch (actor.type) {
|
||||
@@ -69,7 +69,7 @@ export const LogsFilter = ({ control, reset }: Props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-between items-center sticky top-20 z-10 bg-bunker-800">
|
||||
<div className="sticky top-20 z-10 flex items-center justify-between bg-bunker-800">
|
||||
<div className="flex items-center">
|
||||
<Controller
|
||||
control={control}
|
||||
@@ -79,13 +79,13 @@ export const LogsFilter = ({ control, reset }: Props) => {
|
||||
label="Event"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
className="w-40 mr-4"
|
||||
className="mr-4 w-40"
|
||||
>
|
||||
<Select
|
||||
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
||||
{...field}
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
||||
className="w-full border border-mineshaft-500 bg-mineshaft-700 text-mineshaft-100"
|
||||
>
|
||||
{eventTypes.map(({ label, value }) => (
|
||||
<SelectItem value={String(value || "")} key={label}>
|
||||
@@ -105,13 +105,13 @@ export const LogsFilter = ({ control, reset }: Props) => {
|
||||
label="Actor"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
className="w-40 mr-4"
|
||||
className="mr-4 w-40"
|
||||
>
|
||||
<Select
|
||||
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
||||
{...field}
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
||||
className="w-full border border-mineshaft-500 bg-mineshaft-700 text-mineshaft-100"
|
||||
>
|
||||
{data.map((actor) => renderActorSelectItem(actor))}
|
||||
</Select>
|
||||
@@ -127,13 +127,13 @@ export const LogsFilter = ({ control, reset }: Props) => {
|
||||
label="Source"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
className="w-40 mr-4"
|
||||
className="mr-4 w-40"
|
||||
>
|
||||
<Select
|
||||
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
||||
{...field}
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
||||
className="w-full border border-mineshaft-500 bg-mineshaft-700 text-mineshaft-100"
|
||||
>
|
||||
{userAgentTypes.map(({ label, value }) => (
|
||||
<SelectItem value={String(value || "")} key={label}>
|
||||
|
||||
@@ -33,7 +33,7 @@ export const LogsTable = ({ eventType, userAgentType, actor, startDate, endDate
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } = useGetAuditLogs(
|
||||
currentWorkspace?._id ?? "",
|
||||
currentWorkspace?.id ?? "",
|
||||
{
|
||||
eventType,
|
||||
userAgentType,
|
||||
@@ -64,7 +64,7 @@ export const LogsTable = ({ eventType, userAgentType, actor, startDate, endDate
|
||||
data?.pages?.map((group, i) => (
|
||||
<Fragment key={`auditlog-item-${i + 1}`}>
|
||||
{group.map((auditLog) => (
|
||||
<LogsTableRow auditLog={auditLog} key={`audit-log-${auditLog._id}`} />
|
||||
<LogsTableRow auditLog={auditLog} key={`audit-log-${auditLog.id}`} />
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
|
||||
@@ -1,367 +1,358 @@
|
||||
import {
|
||||
Td,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { Td, Tr } from "@app/components/v2";
|
||||
import { eventToNameMap, userAgentTTypeoNameMap } from "@app/hooks/api/auditLogs/constants";
|
||||
import { ActorType, EventType } from "@app/hooks/api/auditLogs/enums";
|
||||
import { Actor, AuditLog, Event } from "@app/hooks/api/auditLogs/types";
|
||||
|
||||
type Props = {
|
||||
auditLog: AuditLog
|
||||
}
|
||||
auditLog: AuditLog;
|
||||
};
|
||||
|
||||
export const LogsTableRow = ({
|
||||
auditLog
|
||||
}: Props) => {
|
||||
const renderActor = (actor: Actor) => {
|
||||
switch (actor.type) {
|
||||
case ActorType.USER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{actor.metadata.email}</p>
|
||||
<p>User</p>
|
||||
</Td>
|
||||
);
|
||||
case ActorType.SERVICE:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`${actor.metadata.name}`}</p>
|
||||
<p>Service token</p>
|
||||
</Td>
|
||||
);
|
||||
case ActorType.IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`${actor.metadata.name}`}</p>
|
||||
<p>Machine Identity</p>
|
||||
</Td>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<Td />
|
||||
);
|
||||
}
|
||||
export const LogsTableRow = ({ auditLog }: Props) => {
|
||||
const renderActor = (actor: Actor) => {
|
||||
switch (actor.type) {
|
||||
case ActorType.USER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{actor.metadata.email}</p>
|
||||
<p>User</p>
|
||||
</Td>
|
||||
);
|
||||
case ActorType.SERVICE:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`${actor.metadata.name}`}</p>
|
||||
<p>Service token</p>
|
||||
</Td>
|
||||
);
|
||||
case ActorType.IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`${actor.metadata.name}`}</p>
|
||||
<p>Machine Identity</p>
|
||||
</Td>
|
||||
);
|
||||
default:
|
||||
return <Td />;
|
||||
}
|
||||
|
||||
const renderMetadata = (event: Event) => {
|
||||
switch (event.type) {
|
||||
case EventType.GET_SECRETS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`# Secrets: ${event.metadata.numberOfSecrets}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.GET_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.AUTHORIZE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UNAUTHORIZE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
{event.metadata.app && (
|
||||
<p>{`Target app: ${event.metadata.app}`}</p>
|
||||
)}
|
||||
{event.metadata.appId && (
|
||||
<p>{`Target app: ${event.metadata.appId}`}</p>
|
||||
)}
|
||||
{event.metadata.targetEnvironment && (
|
||||
<p>{`Target environment: ${event.metadata.targetEnvironment}`}</p>
|
||||
)}
|
||||
{event.metadata.targetEnvironmentId && (
|
||||
<p>{`Target environment ID: ${event.metadata.targetEnvironmentId}`}</p>
|
||||
)}
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
{event.metadata.app && (
|
||||
<p>{`Target App: ${event.metadata.app}`}</p>
|
||||
)}
|
||||
{event.metadata.appId && (
|
||||
<p>{`Target app: ${event.metadata.appId}`}</p>
|
||||
)}
|
||||
{event.metadata.targetEnvironment && (
|
||||
<p>{`Target environment: ${event.metadata.targetEnvironment}`}</p>
|
||||
)}
|
||||
{event.metadata.targetEnvironmentId && (
|
||||
<p>{`Target environment ID: ${event.metadata.targetEnvironmentId}`}</p>
|
||||
)}
|
||||
</Td>
|
||||
);
|
||||
case EventType.ADD_TRUSTED_IP:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`IP: ${event.metadata.ipAddress}${event.metadata.prefix !== undefined ? `/${event.metadata.prefix}` : ""}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_TRUSTED_IP:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`IP: ${event.metadata.ipAddress}${event.metadata.prefix !== undefined ? `/${event.metadata.prefix}` : ""}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_TRUSTED_IP:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`IP: ${event.metadata.ipAddress}${event.metadata.prefix !== undefined ? `/${event.metadata.prefix}` : ""}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_SERVICE_TOKEN:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SERVICE_TOKEN:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`ID: ${event.metadata.identityId}`}</p>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`ID: ${event.metadata.identityId}`}</p>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`ID: ${event.metadata.identityId}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_ENVIRONMENT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
<p>{`Slug: ${event.metadata.slug}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_ENVIRONMENT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Old name: ${event.metadata.oldName}`}</p>
|
||||
<p>{`New name: ${event.metadata.newName}`}</p>
|
||||
<p>{`Old slug: ${event.metadata.oldSlug}`}</p>
|
||||
<p>{`New slug: ${event.metadata.newSlug}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_ENVIRONMENT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
<p>{`Slug: ${event.metadata.slug}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.ADD_WORKSPACE_MEMBER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.REMOVE_WORKSPACE_MEMBER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_FOLDER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.folderPath}`}</p>
|
||||
<p>{`Folder: ${event.metadata.folderName}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_FOLDER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.folderPath}`}</p>
|
||||
<p>{`Old folder: ${event.metadata.oldFolderName}`}</p>
|
||||
<p>{`New folder: ${event.metadata.newFolderName}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_FOLDER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.folderPath}`}</p>
|
||||
<p>{`Folder: ${event.metadata.folderName}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_WEBHOOK:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Secret path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Webhook URL: ${event.metadata.webhookUrl}`}</p>
|
||||
<p>{`Disabled: ${event.metadata.isDisabled}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_WEBHOOK_STATUS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Secret path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Webhook URL: ${event.metadata.webhookUrl}`}</p>
|
||||
<p>{`Disabled: ${event.metadata.isDisabled}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_WEBHOOK:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Secret path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Webhook URL: ${event.metadata.webhookUrl}`}</p>
|
||||
<p>{`Disabled: ${event.metadata.isDisabled}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.GET_SECRET_IMPORTS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`# Imported paths: ${event.metadata.numberOfImports}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_SECRET_IMPORT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Import from env: ${event.metadata.importFromEnvironment}`}</p>
|
||||
<p>{`Import from path: ${event.metadata.importFromSecretPath}`}</p>
|
||||
<p>{`Import to env: ${event.metadata.importToEnvironment}`}</p>
|
||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_SECRET_IMPORT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Import to env: ${event.metadata.importToEnvironment}`}</p>
|
||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SECRET_IMPORT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Import from env: ${event.metadata.importFromEnvironment}`}</p>
|
||||
<p>{`Import from path: ${event.metadata.importFromSecretPath}`}</p>
|
||||
<p>{`Import to env: ${event.metadata.importToEnvironment}`}</p>
|
||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_USER_WORKSPACE_ROLE:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
<p>{`Old role: ${event.metadata.oldRole}`}</p>
|
||||
<p>{`New role: ${event.metadata.newRole}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
{event.metadata.deniedPermissions.map((permission) => {
|
||||
return (
|
||||
<p key={`audit-log-denied-permission-${event.metadata.userId}-${permission.environmentSlug}-${permission.ability}`}>
|
||||
{`Denied env-ability: ${permission.environmentSlug}-${permission.ability}`}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</Td>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<Td />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const renderMetadata = (event: Event) => {
|
||||
switch (event.type) {
|
||||
case EventType.GET_SECRETS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`# Secrets: ${event.metadata.numberOfSecrets}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.GET_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SECRET:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Secret: ${event.metadata.secretKey}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.AUTHORIZE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UNAUTHORIZE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
{event.metadata.app && <p>{`Target app: ${event.metadata.app}`}</p>}
|
||||
{event.metadata.appId && <p>{`Target app: ${event.metadata.appId}`}</p>}
|
||||
{event.metadata.targetEnvironment && (
|
||||
<p>{`Target environment: ${event.metadata.targetEnvironment}`}</p>
|
||||
)}
|
||||
{event.metadata.targetEnvironmentId && (
|
||||
<p>{`Target environment ID: ${event.metadata.targetEnvironmentId}`}</p>
|
||||
)}
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Integration: ${event.metadata.integration}`}</p>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.secretPath}`}</p>
|
||||
{event.metadata.app && <p>{`Target App: ${event.metadata.app}`}</p>}
|
||||
{event.metadata.appId && <p>{`Target app: ${event.metadata.appId}`}</p>}
|
||||
{event.metadata.targetEnvironment && (
|
||||
<p>{`Target environment: ${event.metadata.targetEnvironment}`}</p>
|
||||
)}
|
||||
{event.metadata.targetEnvironmentId && (
|
||||
<p>{`Target environment ID: ${event.metadata.targetEnvironmentId}`}</p>
|
||||
)}
|
||||
</Td>
|
||||
);
|
||||
case EventType.ADD_TRUSTED_IP:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`IP: ${event.metadata.ipAddress}${
|
||||
event.metadata.prefix !== undefined ? `/${event.metadata.prefix}` : ""
|
||||
}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_TRUSTED_IP:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`IP: ${event.metadata.ipAddress}${
|
||||
event.metadata.prefix !== undefined ? `/${event.metadata.prefix}` : ""
|
||||
}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_TRUSTED_IP:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`IP: ${event.metadata.ipAddress}${
|
||||
event.metadata.prefix !== undefined ? `/${event.metadata.prefix}` : ""
|
||||
}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_SERVICE_TOKEN:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SERVICE_TOKEN:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`ID: ${event.metadata.identityId}`}</p>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`ID: ${event.metadata.identityId}`}</p>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_IDENTITY:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`ID: ${event.metadata.identityId}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_ENVIRONMENT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
<p>{`Slug: ${event.metadata.slug}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_ENVIRONMENT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Old name: ${event.metadata.oldName}`}</p>
|
||||
<p>{`New name: ${event.metadata.newName}`}</p>
|
||||
<p>{`Old slug: ${event.metadata.oldSlug}`}</p>
|
||||
<p>{`New slug: ${event.metadata.newSlug}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_ENVIRONMENT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Name: ${event.metadata.name}`}</p>
|
||||
<p>{`Slug: ${event.metadata.slug}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.ADD_WORKSPACE_MEMBER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.REMOVE_WORKSPACE_MEMBER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_FOLDER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.folderPath}`}</p>
|
||||
<p>{`Folder: ${event.metadata.folderName}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_FOLDER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.folderPath}`}</p>
|
||||
<p>{`Old folder: ${event.metadata.oldFolderName}`}</p>
|
||||
<p>{`New folder: ${event.metadata.newFolderName}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_FOLDER:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Path: ${event.metadata.folderPath}`}</p>
|
||||
<p>{`Folder: ${event.metadata.folderName}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_WEBHOOK:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Secret path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Webhook URL: ${event.metadata.webhookUrl}`}</p>
|
||||
<p>{`Disabled: ${event.metadata.isDisabled}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_WEBHOOK_STATUS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Secret path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Webhook URL: ${event.metadata.webhookUrl}`}</p>
|
||||
<p>{`Disabled: ${event.metadata.isDisabled}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_WEBHOOK:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`Secret path: ${event.metadata.secretPath}`}</p>
|
||||
<p>{`Webhook URL: ${event.metadata.webhookUrl}`}</p>
|
||||
<p>{`Disabled: ${event.metadata.isDisabled}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.GET_SECRET_IMPORTS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Environment: ${event.metadata.environment}`}</p>
|
||||
<p>{`# Imported paths: ${event.metadata.numberOfImports}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.CREATE_SECRET_IMPORT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Import from env: ${event.metadata.importFromEnvironment}`}</p>
|
||||
<p>{`Import from path: ${event.metadata.importFromSecretPath}`}</p>
|
||||
<p>{`Import to env: ${event.metadata.importToEnvironment}`}</p>
|
||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_SECRET_IMPORT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Import to env: ${event.metadata.importToEnvironment}`}</p>
|
||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SECRET_IMPORT:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Import from env: ${event.metadata.importFromEnvironment}`}</p>
|
||||
<p>{`Import from path: ${event.metadata.importFromSecretPath}`}</p>
|
||||
<p>{`Import to env: ${event.metadata.importToEnvironment}`}</p>
|
||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_USER_WORKSPACE_ROLE:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
<p>{`Old role: ${event.metadata.oldRole}`}</p>
|
||||
<p>{`New role: ${event.metadata.newRole}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Email: ${event.metadata.email}`}</p>
|
||||
{event.metadata.deniedPermissions.map((permission) => {
|
||||
return (
|
||||
<p
|
||||
key={`audit-log-denied-permission-${event.metadata.userId}-${permission.environmentSlug}-${permission.ability}`}
|
||||
>
|
||||
{`Denied env-ability: ${permission.environmentSlug}-${permission.ability}`}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</Td>
|
||||
);
|
||||
default:
|
||||
return <Td />;
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (dateToFormat: string) => {
|
||||
const date = new Date(dateToFormat);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const formatDate = (dateToFormat: string) => {
|
||||
const date = new Date(dateToFormat);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
|
||||
let hours = date.getHours();
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
let hours = date.getHours();
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
|
||||
// convert from 24h to 12h format
|
||||
const period = hours >= 12 ? "PM" : "AM";
|
||||
hours %= 12;
|
||||
hours = hours || 12; // the hour '0' should be '12'
|
||||
// convert from 24h to 12h format
|
||||
const period = hours >= 12 ? "PM" : "AM";
|
||||
hours %= 12;
|
||||
hours = hours || 12; // the hour '0' should be '12'
|
||||
|
||||
const formattedDate = `${day}-${month}-${year} at ${hours}:${minutes} ${period}`;
|
||||
return formattedDate;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tr className={`log-${auditLog._id} h-10 border-b border-x-0 border-t-0`}>
|
||||
<Td>{formatDate(auditLog.createdAt)}</Td>
|
||||
<Td>{`${eventToNameMap[auditLog.event.type]}`}</Td>
|
||||
{renderActor(auditLog.actor)}
|
||||
<Td>
|
||||
<p>{userAgentTTypeoNameMap[auditLog.userAgentType]}</p>
|
||||
<p>{auditLog.ipAddress}</p>
|
||||
</Td>
|
||||
{renderMetadata(auditLog.event)}
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
const formattedDate = `${day}-${month}-${year} at ${hours}:${minutes} ${period}`;
|
||||
return formattedDate;
|
||||
};
|
||||
|
||||
return (
|
||||
<Tr className={`log-${auditLog.id} h-10 border-x-0 border-b border-t-0`}>
|
||||
<Td>{formatDate(auditLog.createdAt)}</Td>
|
||||
<Td>{`${eventToNameMap[auditLog.event.type]}`}</Td>
|
||||
{renderActor(auditLog.actor)}
|
||||
<Td>
|
||||
<p>{userAgentTTypeoNameMap[auditLog.userAgentType]}</p>
|
||||
<p>{auditLog.ipAddress}</p>
|
||||
</Td>
|
||||
{renderMetadata(auditLog.event)}
|
||||
</Tr>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
Input,
|
||||
Modal,
|
||||
ModalContent
|
||||
} from "@app/components/v2";
|
||||
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import {
|
||||
useAddTrustedIp,
|
||||
useGetMyIp,
|
||||
useUpdateTrustedIp
|
||||
} from "@app/hooks/api";
|
||||
import { useAddTrustedIp, useGetMyIp, useUpdateTrustedIp } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
const schema = yup.object({
|
||||
const schema = yup
|
||||
.object({
|
||||
ipAddress: yup.string().required("IP address is required"),
|
||||
comment: yup.string()
|
||||
}).required();
|
||||
})
|
||||
.required();
|
||||
|
||||
export type FormData = yup.InferType<typeof schema>;
|
||||
|
||||
@@ -32,162 +24,146 @@ type Props = {
|
||||
handlePopUpToggle: (popUpName: keyof UsePopUpState<["trustedIp"]>, state?: boolean) => void;
|
||||
};
|
||||
|
||||
export const IPAllowlistModal = ({
|
||||
popUp,
|
||||
handlePopUpClose,
|
||||
handlePopUpToggle
|
||||
}: Props) => {
|
||||
const { createNotification } = useNotificationContext();
|
||||
const { data, isLoading } = useGetMyIp();
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const addTrustedIp = useAddTrustedIp();
|
||||
const updateTrustedIp = useUpdateTrustedIp();
|
||||
export const IPAllowlistModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
|
||||
const { createNotification } = useNotificationContext();
|
||||
const { data, isLoading } = useGetMyIp();
|
||||
|
||||
const {
|
||||
control,
|
||||
setValue,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { isSubmitting }
|
||||
} = useForm<FormData>({
|
||||
resolver: yupResolver(schema)
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const trustedIpData = popUp?.trustedIp?.data as {
|
||||
ipAddress: string;
|
||||
comment: string;
|
||||
prefix: number;
|
||||
};
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const addTrustedIp = useAddTrustedIp();
|
||||
const updateTrustedIp = useUpdateTrustedIp();
|
||||
|
||||
if (popUp?.trustedIp?.data) {
|
||||
reset({
|
||||
ipAddress: `${trustedIpData.ipAddress}${trustedIpData.prefix !== undefined ? `/${trustedIpData.prefix}` : ""}`,
|
||||
comment: trustedIpData.comment
|
||||
});
|
||||
} else {
|
||||
reset({
|
||||
ipAddress: "",
|
||||
comment: ""
|
||||
});
|
||||
}
|
||||
|
||||
}, [popUp?.trustedIp?.data]);
|
||||
|
||||
const onIPAllowlistModalSubmit = async ({
|
||||
ipAddress,
|
||||
comment
|
||||
}: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.id) return;
|
||||
|
||||
if (popUp?.trustedIp?.data) {
|
||||
await updateTrustedIp.mutateAsync({
|
||||
workspaceId: currentWorkspace.id,
|
||||
trustedIpId: (popUp?.trustedIp?.data as { trustedIpId: string })?.trustedIpId,
|
||||
ipAddress,
|
||||
comment,
|
||||
isActive: true
|
||||
});
|
||||
} else {
|
||||
await addTrustedIp.mutateAsync({
|
||||
workspaceId: currentWorkspace.id,
|
||||
ipAddress,
|
||||
comment,
|
||||
isActive: true
|
||||
});
|
||||
}
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${popUp?.trustedIp?.data ? "updated" : "added"} trusted IP`,
|
||||
type: "success"
|
||||
});
|
||||
|
||||
reset();
|
||||
handlePopUpClose("trustedIp");
|
||||
} catch (err) {
|
||||
createNotification({
|
||||
text: `Failed to ${popUp?.trustedIp?.data ? "update" : "add"} trusted IP`,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
const {
|
||||
control,
|
||||
setValue,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { isSubmitting }
|
||||
} = useForm<FormData>({
|
||||
resolver: yupResolver(schema)
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const trustedIpData = popUp?.trustedIp?.data as {
|
||||
ipAddress: string;
|
||||
comment: string;
|
||||
prefix: number;
|
||||
};
|
||||
|
||||
if (popUp?.trustedIp?.data) {
|
||||
reset({
|
||||
ipAddress: `${trustedIpData.ipAddress}${
|
||||
trustedIpData.prefix !== undefined ? `/${trustedIpData.prefix}` : ""
|
||||
}`,
|
||||
comment: trustedIpData.comment
|
||||
});
|
||||
} else {
|
||||
reset({
|
||||
ipAddress: "",
|
||||
comment: ""
|
||||
});
|
||||
}
|
||||
}, [popUp?.trustedIp?.data]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={popUp?.trustedIp?.isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
handlePopUpToggle("trustedIp", isOpen);
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
<ModalContent title={popUp?.trustedIp?.data ? "Update IP" : "Add IP"}>
|
||||
<form onSubmit={handleSubmit(onIPAllowlistModalSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue=""
|
||||
name="ipAddress"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="IPv4/IPv6 Address / CIDR Notation"
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
>
|
||||
<Input
|
||||
{...field}
|
||||
placeholder="123.456.789.0"
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
{!isLoading && data && (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
type="button"
|
||||
onClick={() => setValue("ipAddress", data)}
|
||||
className="mb-8"
|
||||
>
|
||||
Add current IP address
|
||||
</Button>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue=""
|
||||
name="comment"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Comment"
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
>
|
||||
<Input
|
||||
{...field}
|
||||
placeholder="My IP address"
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<div className="mt-8 flex items-center">
|
||||
<Button
|
||||
className="mr-4"
|
||||
size="sm"
|
||||
type="submit"
|
||||
isLoading={isSubmitting}
|
||||
isDisabled={isSubmitting}
|
||||
>
|
||||
{popUp?.trustedIp?.data ? "Update" : "Add"}
|
||||
</Button>
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
variant="plain"
|
||||
onClick={() => handlePopUpClose("trustedIp")}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
const onIPAllowlistModalSubmit = async ({ ipAddress, comment }: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.id) return;
|
||||
|
||||
if (popUp?.trustedIp?.data) {
|
||||
await updateTrustedIp.mutateAsync({
|
||||
workspaceId: currentWorkspace.id,
|
||||
trustedIpId: (popUp?.trustedIp?.data as { trustedIpId: string })?.trustedIpId,
|
||||
ipAddress,
|
||||
comment,
|
||||
isActive: true
|
||||
});
|
||||
} else {
|
||||
await addTrustedIp.mutateAsync({
|
||||
workspaceId: currentWorkspace.id,
|
||||
ipAddress,
|
||||
comment,
|
||||
isActive: true
|
||||
});
|
||||
}
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${popUp?.trustedIp?.data ? "updated" : "added"} trusted IP`,
|
||||
type: "success"
|
||||
});
|
||||
|
||||
reset();
|
||||
handlePopUpClose("trustedIp");
|
||||
} catch (err) {
|
||||
createNotification({
|
||||
text: `Failed to ${popUp?.trustedIp?.data ? "update" : "add"} trusted IP`,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={popUp?.trustedIp?.isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
handlePopUpToggle("trustedIp", isOpen);
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
<ModalContent title={popUp?.trustedIp?.data ? "Update IP" : "Add IP"}>
|
||||
<form onSubmit={handleSubmit(onIPAllowlistModalSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue=""
|
||||
name="ipAddress"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="IPv4/IPv6 Address / CIDR Notation"
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
>
|
||||
<Input {...field} placeholder="123.456.789.0" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
{!isLoading && data && (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
type="button"
|
||||
onClick={() => setValue("ipAddress", data)}
|
||||
className="mb-8"
|
||||
>
|
||||
Add current IP address
|
||||
</Button>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue=""
|
||||
name="comment"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Comment" isError={Boolean(error)} errorText={error?.message}>
|
||||
<Input {...field} placeholder="My IP address" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<div className="mt-8 flex items-center">
|
||||
<Button
|
||||
className="mr-4"
|
||||
size="sm"
|
||||
type="submit"
|
||||
isLoading={isSubmitting}
|
||||
isDisabled={isSubmitting}
|
||||
>
|
||||
{popUp?.trustedIp?.data ? "Update" : "Add"}
|
||||
</Button>
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
variant="plain"
|
||||
onClick={() => handlePopUpClose("trustedIp")}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -53,9 +53,9 @@ export const IPAllowlistSection = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600">
|
||||
<div className="flex items-center mb-8">
|
||||
<h2 className="text-xl font-semibold flex-1 text-white">IP Allowlist</h2>
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-8 flex items-center">
|
||||
<h2 className="flex-1 text-xl font-semibold text-white">IP Allowlist</h2>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Create}
|
||||
a={ProjectPermissionSub.IpAllowList}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useMemo, useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Link from "next/link";
|
||||
import { faMagnifyingGlass, faPlus, faUsers,faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faMagnifyingGlass, faPlus, faUsers, faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
@@ -40,7 +40,8 @@ import {
|
||||
useOrganization,
|
||||
useSubscription,
|
||||
useUser,
|
||||
useWorkspace} from "@app/context";
|
||||
useWorkspace
|
||||
} from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import {
|
||||
useAddUserToWs,
|
||||
@@ -50,7 +51,8 @@ import {
|
||||
useGetUserWsKey,
|
||||
useGetWorkspaceUsers,
|
||||
useUpdateUserWorkspaceRole,
|
||||
useUploadWsKey} from "@app/hooks/api";
|
||||
useUploadWsKey
|
||||
} from "@app/hooks/api";
|
||||
|
||||
const addMemberFormSchema = z.object({
|
||||
orgMembershipId: z.string().trim()
|
||||
@@ -67,9 +69,9 @@ export const MemberListTab = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { user } = useUser();
|
||||
|
||||
const userId = user?._id || "";
|
||||
const orgId = currentOrg?._id || "";
|
||||
const workspaceId = currentWorkspace?._id || "";
|
||||
const userId = user?.id || "";
|
||||
const orgId = currentOrg?.id || "";
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
|
||||
const { data: roles, isLoading: isRolesLoading } = useGetRoles({
|
||||
orgId,
|
||||
@@ -79,7 +81,7 @@ export const MemberListTab = () => {
|
||||
const { data: wsKey } = useGetUserWsKey(workspaceId);
|
||||
const { data: members, isLoading: isMembersLoading } = useGetWorkspaceUsers(workspaceId);
|
||||
const { data: orgUsers } = useGetOrgUsers(orgId);
|
||||
|
||||
|
||||
const [searchMemberFilter, setSearchMemberFilter] = useState("");
|
||||
|
||||
const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([
|
||||
@@ -101,7 +103,7 @@ export const MemberListTab = () => {
|
||||
const { mutateAsync: updateUserWorkspaceRole } = useUpdateUserWorkspaceRole();
|
||||
|
||||
const onAddMember = async ({ orgMembershipId }: TAddMemberForm) => {
|
||||
if (!currentOrg?._id) return;
|
||||
if (!currentOrg?.id) return;
|
||||
// TODO(akhilmhdh): Move to memory storage
|
||||
const userPrivateKey = localStorage.getItem("PRIVATE_KEY");
|
||||
if (!userPrivateKey || !wsKey) {
|
||||
@@ -110,7 +112,7 @@ export const MemberListTab = () => {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const orgUser = (orgUsers || []).find(({ _id }) => _id === orgMembershipId);
|
||||
const orgUser = (orgUsers || []).find(({ id }) => id === orgMembershipId);
|
||||
if (!orgUser) return;
|
||||
|
||||
try {
|
||||
@@ -137,7 +139,7 @@ export const MemberListTab = () => {
|
||||
|
||||
const handleRemoveUser = async () => {
|
||||
const membershipId = (popUp?.removeMember?.data as { id: string })?.id;
|
||||
if (!currentOrg?._id) return;
|
||||
if (!currentOrg?.id) return;
|
||||
|
||||
try {
|
||||
await removeUserFromWorkspace(membershipId);
|
||||
@@ -156,30 +158,30 @@ export const MemberListTab = () => {
|
||||
};
|
||||
|
||||
const isIamOwner = useMemo(
|
||||
() => members?.find(({ user: u }) => userId === u?._id)?.role === "owner",
|
||||
() => members?.find(({ user: u }) => userId === u?.id)?.role === "owner",
|
||||
[userId, members]
|
||||
);
|
||||
|
||||
const findRoleFromId = useCallback(
|
||||
(roleId: string) => {
|
||||
return (roles || []).find(({ _id: id }) => id === roleId);
|
||||
return (roles || []).find(({ id }) => id === roleId);
|
||||
},
|
||||
[roles]
|
||||
);
|
||||
|
||||
const onRoleChange = async (membershipId: string, role: string) => {
|
||||
if (!currentOrg?._id) return;
|
||||
if (!currentOrg?.id) return;
|
||||
|
||||
try {
|
||||
const isCustomRole = !["admin", "member", "viewer"].includes(role);
|
||||
|
||||
|
||||
if (isCustomRole && subscription && !subscription?.rbac) {
|
||||
handlePopUpOpen("upgradePlan", {
|
||||
description: "You can assign custom roles to members if you upgrade your Infisical plan."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
await updateUserWorkspaceRole({ membershipId, role });
|
||||
createNotification({
|
||||
text: "Successfully updated user role",
|
||||
@@ -215,7 +217,7 @@ export const MemberListTab = () => {
|
||||
({ status, user: u }) => status === "accepted" && !wsUserEmails.has(u.email)
|
||||
);
|
||||
}, [orgUsers, members]);
|
||||
|
||||
|
||||
const onGrantAccess = async (grantedUserId: string, publicKey: string) => {
|
||||
try {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
@@ -239,7 +241,7 @@ export const MemberListTab = () => {
|
||||
userId: grantedUserId,
|
||||
nonce,
|
||||
encryptedKey: ciphertext,
|
||||
workspaceId: currentWorkspace?._id || ""
|
||||
workspaceId: currentWorkspace?.id || ""
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@@ -254,25 +256,20 @@ export const MemberListTab = () => {
|
||||
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<p className="text-xl font-semibold text-mineshaft-100">
|
||||
Members
|
||||
</p>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Create}
|
||||
a={ProjectPermissionSub.Member}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => handlePopUpOpen("addMember")}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Add Member
|
||||
</Button>
|
||||
)}
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<p className="text-xl font-semibold text-mineshaft-100">Members</p>
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Create} a={ProjectPermissionSub.Member}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => handlePopUpOpen("addMember")}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Add Member
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
<Input
|
||||
@@ -296,7 +293,7 @@ export const MemberListTab = () => {
|
||||
{isLoading && <TableSkeleton columns={4} innerKey="project-members" />}
|
||||
{!isLoading &&
|
||||
filterdUsers?.map(
|
||||
({ user: u, inviteEmail, _id: membershipId, status, customRole, role }) => {
|
||||
({ user: u, inviteEmail, id: membershipId, status, customRole, role }) => {
|
||||
const name = u ? `${u.firstName} ${u.lastName}` : "-";
|
||||
const email = u?.email || inviteEmail;
|
||||
|
||||
@@ -315,7 +312,7 @@ export const MemberListTab = () => {
|
||||
value={
|
||||
role === "custom" ? findRoleFromId(customRole)?.slug : role
|
||||
}
|
||||
isDisabled={userId === u?._id || !isAllowed}
|
||||
isDisabled={userId === u?.id || !isAllowed}
|
||||
className="w-40 bg-mineshaft-600"
|
||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
||||
onValueChange={(selectedRole) =>
|
||||
@@ -337,7 +334,7 @@ export const MemberListTab = () => {
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
isDisabled={!isAllowed}
|
||||
onClick={() => onGrantAccess(u?._id, u?.publicKey)}
|
||||
onClick={() => onGrantAccess(u?.id, u?.publicKey)}
|
||||
>
|
||||
Grant Access
|
||||
</Button>
|
||||
@@ -348,7 +345,7 @@ export const MemberListTab = () => {
|
||||
</ProjectPermissionCan>
|
||||
</Td>
|
||||
<Td>
|
||||
{userId !== u?._id && (
|
||||
{userId !== u?.id && (
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Delete}
|
||||
a={ProjectPermissionSub.Member}
|
||||
@@ -360,7 +357,7 @@ export const MemberListTab = () => {
|
||||
variant="plain"
|
||||
ariaLabel="update"
|
||||
className="ml-4"
|
||||
isDisabled={userId === u?._id || !isAllowed}
|
||||
isDisabled={userId === u?.id || !isAllowed}
|
||||
onClick={() =>
|
||||
handlePopUpOpen("removeMember", { id: membershipId })
|
||||
}
|
||||
@@ -405,7 +402,7 @@ export const MemberListTab = () => {
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
{filteredOrgUsers.map(({ _id: orgUserId, user: u }) => (
|
||||
{filteredOrgUsers.map(({ id: orgUserId, user: u }) => (
|
||||
<SelectItem value={orgUserId} key={`org-membership-join-${orgUserId}`}>
|
||||
{u?.email}
|
||||
</SelectItem>
|
||||
|
||||
+6
-6
@@ -38,9 +38,9 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp(["deleteRole"] as const);
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const orgId = currentOrg?._id || "";
|
||||
const workspaceId = currentWorkspace?._id || "";
|
||||
|
||||
const orgId = currentOrg?.id || "";
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
|
||||
const { data: roles, isLoading: isRolesLoading } = useGetRoles({
|
||||
orgId,
|
||||
workspaceId
|
||||
@@ -49,7 +49,7 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
||||
const { mutateAsync: deleteRole } = useDeleteRole();
|
||||
|
||||
const handleRoleDelete = async () => {
|
||||
const { _id: id } = popUp?.deleteRole?.data as TRole<string>;
|
||||
const { id } = popUp?.deleteRole?.data as TRole<string>;
|
||||
try {
|
||||
await deleteRole({
|
||||
orgId,
|
||||
@@ -100,7 +100,7 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
||||
<TBody>
|
||||
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
||||
{(roles as TRole<string>[])?.map((role) => {
|
||||
const { _id: id, name, slug } = role;
|
||||
const { id, name, slug } = role;
|
||||
const isNonMutatable = ["admin", "member", "viewer", "no-access"].includes(slug);
|
||||
|
||||
return (
|
||||
@@ -108,7 +108,7 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
||||
<Td>{name}</Td>
|
||||
<Td>{slug}</Td>
|
||||
<Td>
|
||||
<div className="flex space-x-2 justify-end">
|
||||
<div className="flex justify-end space-x-2">
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
a={ProjectPermissionSub.Role}
|
||||
|
||||
+5
-5
@@ -121,9 +121,9 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||
|
||||
const { createNotification } = useNotificationContext();
|
||||
const { currentOrg } = useOrganization();
|
||||
const orgId = currentOrg?._id || "";
|
||||
const orgId = currentOrg?.id || "";
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const workspaceId = currentWorkspace?._id || "";
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
@@ -139,12 +139,12 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||
const { mutateAsync: updateRole } = useUpdateRole();
|
||||
|
||||
const handleRoleUpdate = async (el: TFormSchema) => {
|
||||
if (!role?._id) return;
|
||||
|
||||
if (!role?.id) return;
|
||||
|
||||
try {
|
||||
await updateRole({
|
||||
orgId,
|
||||
id: role?._id,
|
||||
id: role?.id,
|
||||
workspaceId,
|
||||
...el,
|
||||
permissions: formRolePermission2API(el.permissions)
|
||||
|
||||
+494
-490
File diff suppressed because it is too large
Load Diff
+124
-68
@@ -1,47 +1,44 @@
|
||||
import { faKey, faPencil,faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faKey, faPencil, faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { format } from "date-fns";
|
||||
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
EmptyState,
|
||||
IconButton,
|
||||
Switch,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableSkeleton,
|
||||
TBody,
|
||||
Td,
|
||||
Th,
|
||||
THead,
|
||||
Tr
|
||||
EmptyState,
|
||||
IconButton,
|
||||
Switch,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableSkeleton,
|
||||
TBody,
|
||||
Td,
|
||||
Th,
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub , useWorkspace } from "@app/context";
|
||||
import {
|
||||
useGetWorkspaceServiceTokenDataV3,
|
||||
useUpdateServiceTokenV3
|
||||
} from "@app/hooks/api";
|
||||
import { ServiceTokenV3TrustedIp } from "@app/hooks/api/serviceTokens/types"
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { useGetWorkspaceServiceTokenDataV3, useUpdateServiceTokenV3 } from "@app/hooks/api";
|
||||
import { ServiceTokenV3TrustedIp } from "@app/hooks/api/serviceTokens/types";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
type Props = {
|
||||
handlePopUpOpen: (
|
||||
popUpName: keyof UsePopUpState<["deleteServiceTokenV3", "serviceTokenV3"]>,
|
||||
data?: {
|
||||
serviceTokenDataId?: string;
|
||||
name?: string;
|
||||
role?: string;
|
||||
customRole?: {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
trustedIps?: ServiceTokenV3TrustedIp[];
|
||||
accessTokenTTL?: number;
|
||||
isRefreshTokenRotationEnabled?: boolean;
|
||||
}
|
||||
) => void;
|
||||
};
|
||||
handlePopUpOpen: (
|
||||
popUpName: keyof UsePopUpState<["deleteServiceTokenV3", "serviceTokenV3"]>,
|
||||
data?: {
|
||||
serviceTokenDataId?: string;
|
||||
name?: string;
|
||||
role?: string;
|
||||
customRole?: {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
trustedIps?: ServiceTokenV3TrustedIp[];
|
||||
accessTokenTTL?: number;
|
||||
isRefreshTokenRotationEnabled?: boolean;
|
||||
}
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const ServiceTokenV3Table = ({
|
||||
handlePopUpOpen
|
||||
@@ -51,30 +48,29 @@ export const ServiceTokenV3Table = ({
|
||||
const { data, isLoading } = useGetWorkspaceServiceTokenDataV3(currentWorkspace?.id || "");
|
||||
const { mutateAsync: updateMutateAsync } = useUpdateServiceTokenV3();
|
||||
|
||||
const handleToggleServiceTokenDataStatus = async ({
|
||||
const handleToggleServiceTokenDataStatus = async ({
|
||||
serviceTokenDataId,
|
||||
isActive
|
||||
}: {
|
||||
serviceTokenDataId: string;
|
||||
isActive: boolean;
|
||||
}) => {
|
||||
try {
|
||||
await updateMutateAsync({
|
||||
serviceTokenDataId,
|
||||
isActive
|
||||
}: {
|
||||
serviceTokenDataId: string;
|
||||
isActive: boolean;
|
||||
}) => {
|
||||
try {
|
||||
await updateMutateAsync({
|
||||
serviceTokenDataId,
|
||||
isActive
|
||||
});
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${isActive ? "enabled" : "disabled"} service token v3`,
|
||||
type: "success"
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
createNotification({
|
||||
text: `Failed to ${isActive ? "enable" : "disable"} service token v3`,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
createNotification({
|
||||
text: `Successfully ${isActive ? "enabled" : "disabled"} service token v3`,
|
||||
type: "success"
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
createNotification({
|
||||
text: `Failed to ${isActive ? "enable" : "disable"} service token v3`,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -203,16 +199,76 @@ export const ServiceTokenV3Table = ({
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
{!isLoading && data && data?.length === 0 && (
|
||||
<Tr>
|
||||
<Td colSpan={7}>
|
||||
<EmptyState title="No service token v3 on file" icon={faKey} />
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
</TBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</Td>
|
||||
<Td>{accessTokenTTL}</Td>
|
||||
<Td>{format(new Date(createdAt), "yyyy-MM-dd")}</Td>
|
||||
<Td>{expiresAt ? format(new Date(expiresAt), "yyyy-MM-dd") : "-"}</Td>
|
||||
<Td className="flex justify-end">
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
a={ProjectPermissionSub.ServiceTokens}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<IconButton
|
||||
onClick={async () => {
|
||||
handlePopUpOpen("serviceTokenV3", {
|
||||
serviceTokenDataId: id,
|
||||
name,
|
||||
role,
|
||||
customRole,
|
||||
trustedIps,
|
||||
accessTokenTTL,
|
||||
isRefreshTokenRotationEnabled
|
||||
});
|
||||
}}
|
||||
size="lg"
|
||||
colorSchema="primary"
|
||||
variant="plain"
|
||||
ariaLabel="update"
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
<FontAwesomeIcon icon={faPencil} />
|
||||
</IconButton>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Delete}
|
||||
a={ProjectPermissionSub.ServiceTokens}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
handlePopUpOpen("deleteServiceTokenV3", {
|
||||
serviceTokenDataId: id,
|
||||
name
|
||||
});
|
||||
}}
|
||||
size="lg"
|
||||
colorSchema="danger"
|
||||
variant="plain"
|
||||
ariaLabel="update"
|
||||
className="ml-4"
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
<FontAwesomeIcon icon={faXmark} />
|
||||
</IconButton>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
)}
|
||||
{!isLoading && data && data?.length === 0 && (
|
||||
<Tr>
|
||||
<Td colSpan={7}>
|
||||
<EmptyState title="No service token v3 on file" icon={faKey} />
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
</TBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user