diff --git a/src/api/services/permissions.ts b/src/api/services/permissions.ts
index d4ba39174..f19653b96 100644
--- a/src/api/services/permissions.ts
+++ b/src/api/services/permissions.ts
@@ -92,7 +92,5 @@ export function updatePermission(permission: PermissionTable) {
}
export function deletePermission(id: string) {
- return IncidentCommander.patch(`/permissions?id=eq.${id}`, {
- deleted_at: "now()"
- });
+ return IncidentCommander.delete(`/permissions?id=eq.${id}`);
}
diff --git a/src/components/Configs/ConfigLink/ConfigLink.tsx b/src/components/Configs/ConfigLink/ConfigLink.tsx
index 36ac9d4f4..c27468184 100644
--- a/src/components/Configs/ConfigLink/ConfigLink.tsx
+++ b/src/components/Configs/ConfigLink/ConfigLink.tsx
@@ -1,6 +1,5 @@
import { getConfigsByID } from "@flanksource-ui/api/services/configs";
import { ConfigIcon } from "@flanksource-ui/ui/Icons/ConfigIcon";
-import TextSkeletonLoader from "@flanksource-ui/ui/SkeletonLoader/TextSkeletonLoader";
import { useQuery } from "@tanstack/react-query";
import clsx from "clsx";
import { HTMLAttributeAnchorTarget } from "react";
@@ -26,7 +25,7 @@ export default function ConfigLink({
showPrimaryIcon = true,
showSecondaryIcon = true
}: ConfigLinkProps) {
- const { data: configFromRequest, isLoading } = useQuery({
+ const { data: configFromRequest } = useQuery({
queryKey: ["config", configId, config],
queryFn: () => getConfigsByID(configId!),
// Only run the query if we have a configId and we don't have a config
@@ -35,9 +34,9 @@ export default function ConfigLink({
const data = config || configFromRequest;
- if (isLoading) {
- return ;
- }
+ // if (isLoading) {
+ // return ;
+ // }
if (!data) {
return null;
diff --git a/src/components/Connections/ConnectionFormModal.tsx b/src/components/Connections/ConnectionFormModal.tsx
index 8db2a6dd4..66eb9c9b7 100644
--- a/src/components/Connections/ConnectionFormModal.tsx
+++ b/src/components/Connections/ConnectionFormModal.tsx
@@ -1,6 +1,8 @@
+import { Tab, Tabs } from "@flanksource-ui/ui/Tabs/Tabs";
import React, { useEffect, useState } from "react";
import { Icon } from "../../ui/Icons/Icon";
import { Modal } from "../../ui/Modal";
+import PermissionsView from "../Permissions/PermissionsView";
import ConnectionForm from "./ConnectionForm";
import ConnectionListView from "./ConnectionListView";
import ConnectionSpecEditor from "./ConnectionSpecEditor";
@@ -81,6 +83,8 @@ export default function ConnectionFormModal({
ConnectionType | undefined
>(() => connectionTypes.find((item) => item.title === formValue?.type));
+ const [activeTab, setActiveTab] = useState<"form" | "permissions">("form");
+
useEffect(() => {
let connection = connectionTypes.find(
(item) => item.value === formValue?.type
@@ -93,35 +97,76 @@ export default function ConnectionFormModal({
connectionType;
return (
-
-
- {typeof connectionType?.icon === "string" ? (
-
- ) : (
- connectionType.icon
- )}
-
- {connectionType.title} Connection Details
-
+
+ {typeof connectionType?.icon === "string" ? (
+
+ ) : (
+ connectionType.icon
+ )}
+
+ {connectionType.title} Connection Details
- ) : (
- Select Connection Type
- )
- }
- onClose={() => {
- setIsOpen(false);
- }}
- open={isOpen}
- bodyClass="flex flex-col w-full flex-1 h-full overflow-y-auto"
- helpLink="reference/connections/"
- >
- {type ? (
+
+ ) : (
+ Select Connection Type
+ )
+ }
+ onClose={() => {
+ setIsOpen(false);
+ }}
+ open={isOpen}
+ size="full"
+ bodyClass="flex flex-col w-full flex-1 h-full overflow-y-auto"
+ helpLink="reference/connections/"
+ containerClassName="h-full overflow-auto"
+ >
+ {type ? (
+ formValue?.id ? (
+ setActiveTab(label)}
+ >
+
+ setConnectionType(undefined)}
+ connectionType={type}
+ onConnectionSubmit={onConnectionSubmit}
+ onConnectionDelete={onConnectionDelete}
+ formValue={formValue}
+ className={className}
+ isSubmitting={isSubmitting}
+ isDeleting={isDeleting}
+ />
+
+
+
+
+
+
+ ) : (
setConnectionType(undefined)}
connectionType={type}
@@ -132,20 +177,20 @@ export default function ConnectionFormModal({
isSubmitting={isSubmitting}
isDeleting={isDeleting}
/>
- ) : formValue?.id ? (
- setConnectionType(undefined)}
- onConnectionSubmit={onConnectionSubmit}
- onConnectionDelete={onConnectionDelete}
- formValue={formValue}
- className={className}
- isSubmitting={isSubmitting}
- isDeleting={isDeleting}
- />
- ) : (
-
- )}
-
-
+ )
+ ) : formValue?.id ? (
+ setConnectionType(undefined)}
+ onConnectionSubmit={onConnectionSubmit}
+ onConnectionDelete={onConnectionDelete}
+ formValue={formValue}
+ className={className}
+ isSubmitting={isSubmitting}
+ isDeleting={isDeleting}
+ />
+ ) : (
+
+ )}
+
);
}
diff --git a/src/components/Permissions/ManagePermissions/Forms/PermissionForm.tsx b/src/components/Permissions/ManagePermissions/Forms/PermissionForm.tsx
index e9e5a9429..d788d5553 100644
--- a/src/components/Permissions/ManagePermissions/Forms/PermissionForm.tsx
+++ b/src/components/Permissions/ManagePermissions/Forms/PermissionForm.tsx
@@ -6,6 +6,7 @@ import { PermissionTable } from "@flanksource-ui/api/types/permissions";
import FormikCheckbox from "@flanksource-ui/components/Forms/Formik/FormikCheckbox";
import FormikTextArea from "@flanksource-ui/components/Forms/Formik/FormikTextArea";
import FormikTextInput from "@flanksource-ui/components/Forms/Formik/FormikTextInput";
+import CanEditResource from "@flanksource-ui/components/Settings/CanEditResource";
import {
toastError,
toastSuccess
@@ -29,7 +30,7 @@ import PermissionsSubjectControls from "./PermissionSubjectControls";
type PermissionFormProps = {
onClose: () => void;
isOpen: boolean;
- data?: PermissionTable;
+ data?: Partial;
};
export default function PermissionForm({
@@ -43,7 +44,8 @@ export default function PermissionForm({
data?.config_id ||
data?.canary_id ||
data?.canary_id ||
- data?.playbook_id
+ data?.playbook_id ||
+ data?.connection_id
);
}, [data]);
@@ -107,7 +109,7 @@ export default function PermissionForm({
config_id: data?.config_id,
canary_id: data?.canary_id,
playbook_id: data?.playbook_id,
- deny: data?.deny,
+ deny: data?.deny ?? false,
description: data?.description,
connection_id: data?.connection_id,
created_at: data?.created_at,
@@ -147,34 +149,42 @@ export default function PermissionForm({
-
-
- {data?.id && (
-
+ {data?.id && (
+
+ )}
+
+ ) : undefined
+ }
+ type="submit"
+ text={data?.id ? "Save" : isLoading ? "Saving ..." : "Save"}
+ className="btn-primary"
/>
- )}
-
- ) : undefined
- }
- type="submit"
- text={data?.id ? "Save" : isLoading ? "Saving ..." : "Save"}
- className="btn-primary"
- />
-
-
+
+
+
diff --git a/src/components/Permissions/PermissionsView.tsx b/src/components/Permissions/PermissionsView.tsx
index 1406fa2a6..557278631 100644
--- a/src/components/Permissions/PermissionsView.tsx
+++ b/src/components/Permissions/PermissionsView.tsx
@@ -2,10 +2,14 @@ import {
fetchPermissions,
FetchPermissionsInput
} from "@flanksource-ui/api/services/permissions";
-import { PermissionAPIResponse } from "@flanksource-ui/api/types/permissions";
+import {
+ PermissionAPIResponse,
+ PermissionTable
+} from "@flanksource-ui/api/types/permissions";
import useReactTablePaginationState from "@flanksource-ui/ui/DataTable/Hooks/useReactTablePaginationState";
import { useQuery } from "@tanstack/react-query";
import { useEffect, useState } from "react";
+import { Button } from "..";
import PermissionForm from "./ManagePermissions/Forms/PermissionForm";
import PermissionsTable from "./PermissionsTable";
@@ -13,16 +17,21 @@ type PermissionsViewProps = {
permissionRequest: FetchPermissionsInput;
setIsLoading?: (isLoading: boolean) => void;
hideResourceColumn?: boolean;
+ newPermissionData?: Partial;
+ showAddPermission?: boolean;
};
export default function PermissionsView({
permissionRequest,
setIsLoading = () => {},
- hideResourceColumn = false
+ hideResourceColumn = false,
+ newPermissionData,
+ showAddPermission = false
}: PermissionsViewProps) {
const [selectedPermission, setSelectedPermission] =
useState();
const { pageSize, pageIndex } = useReactTablePaginationState();
+ const [isPermissionModalOpen, setIsPermissionModalOpen] = useState(false);
const { isLoading, data, refetch } = useQuery({
queryKey: [
@@ -51,6 +60,17 @@ export default function PermissionsView({
return (
<>
+ {showAddPermission && (
+
+
+
+ )}
)}
+ {showAddPermission && (
+ {
+ setIsPermissionModalOpen(false);
+ refetch();
+ }}
+ />
+ )}
>
);
}
diff --git a/src/components/Playbooks/Settings/PlaybookSpecFormModal.tsx b/src/components/Playbooks/Settings/PlaybookSpecFormModal.tsx
index 56ed61354..92f49b47a 100644
--- a/src/components/Playbooks/Settings/PlaybookSpecFormModal.tsx
+++ b/src/components/Playbooks/Settings/PlaybookSpecFormModal.tsx
@@ -1,5 +1,8 @@
import { PlaybookSpec } from "@flanksource-ui/api/types/playbooks";
+import PermissionsView from "@flanksource-ui/components/Permissions/PermissionsView";
import { Modal } from "@flanksource-ui/ui/Modal";
+import { Tab, Tabs } from "@flanksource-ui/ui/Tabs/Tabs";
+import { useState } from "react";
import PlaybookSpecModalTitle from "../PlaybookSpecModalTitle";
import PlaybookSpecsForm from "./PlaybookSpecsForm";
@@ -16,6 +19,8 @@ export default function PlaybookSpecFormModal({
onClose,
...props
}: PlaybookSpecFormModalProps) {
+ const [activeTab, setActiveTab] = useState<"form" | "permissions">("form");
+
return (
-
+ {playbook?.id ? (
+ setActiveTab(label)}
+ >
+
+
+
+
+
+
+
+
+ ) : (
+
+ )}
);
}
diff --git a/src/components/SchemaResourcePage/resourceTypes.tsx b/src/components/SchemaResourcePage/resourceTypes.tsx
index faa8d88b2..b9461a134 100644
--- a/src/components/SchemaResourcePage/resourceTypes.tsx
+++ b/src/components/SchemaResourcePage/resourceTypes.tsx
@@ -19,7 +19,8 @@ export type SchemaResourceType = {
| "Connections"
| "Log Backends"
| "Notifications"
- | "Feature Flags";
+ | "Feature Flags"
+ | "Permissions";
table:
| "teams"
| "incident_rules"
@@ -29,7 +30,8 @@ export type SchemaResourceType = {
| "connections"
| "logging_backends"
| "notifications"
- | "properties";
+ | "properties"
+ | "permissions";
api: "incident-commander" | "canary-checker" | "config-db";
featureName: string;
resourceName: string;
diff --git a/src/components/Settings/ResourceTable.tsx b/src/components/Settings/ResourceTable.tsx
index a21aaecbb..ba2cd7bd0 100644
--- a/src/components/Settings/ResourceTable.tsx
+++ b/src/components/Settings/ResourceTable.tsx
@@ -266,7 +266,8 @@ const permanentlyHiddenColumnsForTableMap: Record<
canaries: ["namespace"],
config_scrapers: ["schedule", "namespace"],
incident_rules: ["schedule", "namespace"],
- teams: ["schedule", "namespace"]
+ teams: ["schedule", "namespace"],
+ permissions: ["schedule", "namespace"]
};
type ResourceTableProps = {
diff --git a/src/pages/Settings/ConnectionsPage.tsx b/src/pages/Settings/ConnectionsPage.tsx
index e450d926e..f4653e474 100644
--- a/src/pages/Settings/ConnectionsPage.tsx
+++ b/src/pages/Settings/ConnectionsPage.tsx
@@ -166,18 +166,17 @@ export function ConnectionsPage() {
setEditedRow(val);
}}
/>
-
- deleteConnection(data)}
- isSubmitting={isSubmitting}
- isDeleting={isDeleting}
- formValue={editedRow}
- key={editedRow?.id || "connection-form"}
- />
+ deleteConnection(data)}
+ isSubmitting={isSubmitting}
+ isDeleting={isDeleting}
+ formValue={editedRow}
+ key={editedRow?.id || "connection-form"}
+ />
>
);
diff --git a/src/pages/Settings/PermissionsPage.tsx b/src/pages/Settings/PermissionsPage.tsx
index a6f2ba767..c601e9e95 100644
--- a/src/pages/Settings/PermissionsPage.tsx
+++ b/src/pages/Settings/PermissionsPage.tsx
@@ -1,4 +1,3 @@
-import { SearchLayout } from "@flanksource-ui/components/Layout/SearchLayout";
import { AuthorizationAccessCheck } from "@flanksource-ui/components/Permissions/AuthorizationAccessCheck";
import AddPermissionButton from "@flanksource-ui/components/Permissions/ManagePermissions/Forms/AddPermissionButton";
import PermissionsView from "@flanksource-ui/components/Permissions/PermissionsView";
@@ -8,6 +7,7 @@ import {
BreadcrumbRoot
} from "@flanksource-ui/ui/BreadcrumbNav";
import { Head } from "@flanksource-ui/ui/Head";
+import { SearchLayout } from "@flanksource-ui/ui/Layout/SearchLayout";
import { useQueryClient } from "@tanstack/react-query";
import { useState } from "react";