From 4709f9826c42a52d88a766a47aa5cdb4078b4d1c Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Thu, 30 Oct 2025 19:01:00 +1000 Subject: [PATCH] Permissions polish for restricted users --- frontend/src/components/EmptyData.tsx | 39 +++++--- frontend/src/components/HasPermission.tsx | 40 ++------- frontend/src/components/SiteMenu.tsx | 58 +++++++----- frontend/src/modals/PermissionsModal.tsx | 37 +++++++- frontend/src/modals/ProxyHostModal.tsx | 35 ++++---- frontend/src/modules/Permissions.ts | 49 ++++++++++ frontend/src/pages/Access/Table.tsx | 30 ++++--- frontend/src/pages/Access/TableWrapper.tsx | 19 ++-- frontend/src/pages/Access/index.tsx | 3 +- frontend/src/pages/AuditLog/index.tsx | 3 +- frontend/src/pages/Certificates/Table.tsx | 51 ++++++----- .../src/pages/Certificates/TableWrapper.tsx | 90 ++++++++++--------- frontend/src/pages/Certificates/index.tsx | 3 +- frontend/src/pages/Dashboard/index.tsx | 9 +- frontend/src/pages/Nginx/DeadHosts/Table.tsx | 51 ++++++----- .../pages/Nginx/DeadHosts/TableWrapper.tsx | 15 ++-- frontend/src/pages/Nginx/DeadHosts/index.tsx | 3 +- frontend/src/pages/Nginx/ProxyHosts/Table.tsx | 51 ++++++----- .../pages/Nginx/ProxyHosts/TableWrapper.tsx | 20 +++-- frontend/src/pages/Nginx/ProxyHosts/index.tsx | 3 +- .../pages/Nginx/RedirectionHosts/Table.tsx | 51 ++++++----- .../Nginx/RedirectionHosts/TableWrapper.tsx | 24 ++--- .../pages/Nginx/RedirectionHosts/index.tsx | 3 +- frontend/src/pages/Nginx/Streams/Table.tsx | 51 ++++++----- .../src/pages/Nginx/Streams/TableWrapper.tsx | 16 ++-- frontend/src/pages/Nginx/Streams/index.tsx | 3 +- frontend/src/pages/Settings/index.tsx | 3 +- frontend/src/pages/Users/index.tsx | 3 +- 28 files changed, 457 insertions(+), 306 deletions(-) create mode 100644 frontend/src/modules/Permissions.ts diff --git a/frontend/src/components/EmptyData.tsx b/frontend/src/components/EmptyData.tsx index d79b4a5a..46a9664c 100644 --- a/frontend/src/components/EmptyData.tsx +++ b/frontend/src/components/EmptyData.tsx @@ -1,8 +1,9 @@ import type { Table as ReactTable } from "@tanstack/react-table"; import cn from "classnames"; import type { ReactNode } from "react"; -import { Button } from "src/components"; +import { Button, HasPermission } from "src/components"; import { T } from "src/locale"; +import { type ADMIN, MANAGE, type Permission, type Section } from "src/modules/Permissions"; interface Props { tableInstance: ReactTable; @@ -12,8 +13,20 @@ interface Props { objects: string; color?: string; customAddBtn?: ReactNode; + permissionSection?: Section | typeof ADMIN; + permission?: Permission; } -function EmptyData({ tableInstance, onNew, isFiltered, object, objects, color = "primary", customAddBtn }: Props) { +function EmptyData({ + tableInstance, + onNew, + isFiltered, + object, + objects, + color = "primary", + customAddBtn, + permissionSection, + permission, +}: Props) { return ( @@ -27,16 +40,18 @@ function EmptyData({ tableInstance, onNew, isFiltered, object, objects, color =

-

- -

- {customAddBtn ? ( - customAddBtn - ) : ( - - )} + +

+ +

+ {customAddBtn ? ( + customAddBtn + ) : ( + + )} +
)} diff --git a/frontend/src/components/HasPermission.tsx b/frontend/src/components/HasPermission.tsx index 7c348c45..c038066b 100644 --- a/frontend/src/components/HasPermission.tsx +++ b/frontend/src/components/HasPermission.tsx @@ -3,25 +3,29 @@ import Alert from "react-bootstrap/Alert"; import { Loading, LoadingPage } from "src/components"; import { useUser } from "src/hooks"; import { T } from "src/locale"; +import { type ADMIN, hasPermission, type Permission, type Section } from "src/modules/Permissions"; interface Props { - permission: string; - type: "manage" | "view"; + section?: Section | typeof ADMIN; + permission: Permission; hideError?: boolean; children?: ReactNode; pageLoading?: boolean; loadingNoLogo?: boolean; } function HasPermission({ + section, permission, - type, children, hideError = false, pageLoading = false, loadingNoLogo = false, }: Props) { const { data, isLoading } = useUser("me"); - const perms = data?.permissions; + + if (!section) { + return <>{children}; + } if (isLoading) { if (hideError) { @@ -33,33 +37,7 @@ function HasPermission({ return ; } - let allowed = permission === ""; - const acceptable = ["manage", type]; - - switch (permission) { - case "admin": - allowed = data?.roles?.includes("admin") || false; - break; - case "proxyHosts": - allowed = acceptable.indexOf(perms?.proxyHosts || "") !== -1; - break; - case "redirectionHosts": - allowed = acceptable.indexOf(perms?.redirectionHosts || "") !== -1; - break; - case "deadHosts": - allowed = acceptable.indexOf(perms?.deadHosts || "") !== -1; - break; - case "streams": - allowed = acceptable.indexOf(perms?.streams || "") !== -1; - break; - case "accessLists": - allowed = acceptable.indexOf(perms?.accessLists || "") !== -1; - break; - case "certificates": - allowed = acceptable.indexOf(perms?.certificates || "") !== -1; - break; - } - + const allowed = hasPermission(section, permission, data?.permissions, data?.roles); if (allowed) { return <>{children}; } diff --git a/frontend/src/components/SiteMenu.tsx b/frontend/src/components/SiteMenu.tsx index e38de683..3a0b0065 100644 --- a/frontend/src/components/SiteMenu.tsx +++ b/frontend/src/components/SiteMenu.tsx @@ -11,14 +11,26 @@ import cn from "classnames"; import React from "react"; import { HasPermission, NavLink } from "src/components"; import { T } from "src/locale"; +import { + ACCESS_LISTS, + ADMIN, + CERTIFICATES, + DEAD_HOSTS, + type MANAGE, + PROXY_HOSTS, + REDIRECTION_HOSTS, + type Section, + STREAMS, + VIEW, +} from "src/modules/Permissions"; interface MenuItem { label: string; icon?: React.ElementType; to?: string; items?: MenuItem[]; - permission?: string; - permissionType?: "view" | "manage"; + permissionSection?: Section | typeof ADMIN; + permission?: typeof VIEW | typeof MANAGE; } const menuItems: MenuItem[] = [ @@ -34,26 +46,26 @@ const menuItems: MenuItem[] = [ { to: "/nginx/proxy", label: "proxy-hosts", - permission: "proxyHosts", - permissionType: "view", + permissionSection: PROXY_HOSTS, + permission: VIEW, }, { to: "/nginx/redirection", label: "redirection-hosts", - permission: "redirectionHosts", - permissionType: "view", + permissionSection: REDIRECTION_HOSTS, + permission: VIEW, }, { to: "/nginx/stream", label: "streams", - permission: "streams", - permissionType: "view", + permissionSection: STREAMS, + permission: VIEW, }, { to: "/nginx/404", label: "dead-hosts", - permission: "deadHosts", - permissionType: "view", + permissionSection: DEAD_HOSTS, + permission: VIEW, }, ], }, @@ -61,33 +73,33 @@ const menuItems: MenuItem[] = [ to: "/access", icon: IconLock, label: "access-lists", - permission: "accessLists", - permissionType: "view", + permissionSection: ACCESS_LISTS, + permission: VIEW, }, { to: "/certificates", icon: IconShield, label: "certificates", - permission: "certificates", - permissionType: "view", + permissionSection: CERTIFICATES, + permission: VIEW, }, { to: "/users", icon: IconUser, label: "users", - permission: "admin", + permissionSection: ADMIN, }, { to: "/audit-log", icon: IconBook, label: "auditlogs", - permission: "admin", + permissionSection: ADMIN, }, { to: "/settings", icon: IconSettings, label: "settings", - permission: "admin", + permissionSection: ADMIN, }, ]; @@ -99,8 +111,8 @@ const getMenuItem = (item: MenuItem, onClick?: () => void) => { return (
  • @@ -122,8 +134,8 @@ const getMenuDropown = (item: MenuItem, onClick?: () => void) => { return (
  • @@ -147,8 +159,8 @@ const getMenuDropown = (item: MenuItem, onClick?: () => void) => { return ( diff --git a/frontend/src/modals/PermissionsModal.tsx b/frontend/src/modals/PermissionsModal.tsx index 6d978a0a..d363de9e 100644 --- a/frontend/src/modals/PermissionsModal.tsx +++ b/frontend/src/modals/PermissionsModal.tsx @@ -47,11 +47,41 @@ const PermissionsModal = EasyModal.create(({ id, visible, remove }: Props) => { }); }; + // given the field and clicked permission, intelligently set the value, and + // other values that depends on it. + const handleChange = (form: any, field: any, perm: string) => { + if (field.name === "proxyHosts" && perm !== "hidden" && form.values.accessLists === "hidden") { + form.setFieldValue("accessLists", "view"); + } + // certs are required for proxy and redirection hosts, and streams + if ( + ["proxyHosts", "redirectionHosts", "deadHosts", "streams"].includes(field.name) && + perm !== "hidden" && + form.values.certificates === "hidden" + ) { + form.setFieldValue("certificates", "view"); + } + + form.setFieldValue(field.name, perm); + }; + const getPermissionButtons = (field: any, form: any) => { const isManage = field.value === "manage"; const isView = field.value === "view"; const isHidden = field.value === "hidden"; + let hiddenDisabled = false; + if (field.name === "accessLists") { + hiddenDisabled = form.values.proxyHosts !== "hidden"; + } + if (field.name === "certificates") { + hiddenDisabled = + form.values.proxyHosts !== "hidden" || + form.values.redirectionHosts !== "hidden" || + form.values.deadHosts !== "hidden" || + form.values.streams !== "hidden"; + } + return (
    @@ -63,7 +93,7 @@ const PermissionsModal = EasyModal.create(({ id, visible, remove }: Props) => { autoComplete="off" value="manage" checked={field.value === "manage"} - onChange={() => form.setFieldValue(field.name, "manage")} + onChange={() => handleChange(form, field, "manage")} />
    diff --git a/frontend/src/pages/Access/index.tsx b/frontend/src/pages/Access/index.tsx index 71fd23fe..9c4624cb 100644 --- a/frontend/src/pages/Access/index.tsx +++ b/frontend/src/pages/Access/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { ACCESS_LISTS, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const Access = () => { return ( - + ); diff --git a/frontend/src/pages/AuditLog/index.tsx b/frontend/src/pages/AuditLog/index.tsx index af124229..4bdc2d07 100644 --- a/frontend/src/pages/AuditLog/index.tsx +++ b/frontend/src/pages/AuditLog/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { ADMIN, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const AuditLog = () => { return ( - + ); diff --git a/frontend/src/pages/Certificates/Table.tsx b/frontend/src/pages/Certificates/Table.tsx index e880d049..ce816f9b 100644 --- a/frontend/src/pages/Certificates/Table.tsx +++ b/frontend/src/pages/Certificates/Table.tsx @@ -8,10 +8,12 @@ import { DomainsFormatter, EmptyData, GravatarFormatter, + HasPermission, } from "src/components"; import { TableLayout } from "src/components/Table/TableLayout"; import { intl, T } from "src/locale"; import { showCustomCertificateModal, showDNSCertificateModal, showHTTPCertificateModal } from "src/modals"; +import { CERTIFICATES, MANAGE } from "src/modules/Permissions"; interface Props { data: Certificate[]; @@ -125,29 +127,31 @@ export default function Table({ data, isFetching, onDelete, onRenew, onDownload, - { - e.preventDefault(); - onDownload?.(info.row.original.id); - }} - > - - - -
    - { - e.preventDefault(); - onDelete?.(info.row.original.id); - }} - > - - - + + { + e.preventDefault(); + onDownload?.(info.row.original.id); + }} + > + + + + ); @@ -223,6 +227,7 @@ export default function Table({ data, isFetching, onDelete, onRenew, onDownload, isFiltered={isFiltered} color="pink" customAddBtn={customAddBtn} + permissionSection={CERTIFICATES} /> } /> diff --git a/frontend/src/pages/Certificates/TableWrapper.tsx b/frontend/src/pages/Certificates/TableWrapper.tsx index 2a270d19..14dfc417 100644 --- a/frontend/src/pages/Certificates/TableWrapper.tsx +++ b/frontend/src/pages/Certificates/TableWrapper.tsx @@ -2,7 +2,7 @@ import { IconHelp, IconSearch } from "@tabler/icons-react"; import { useState } from "react"; import Alert from "react-bootstrap/Alert"; import { deleteCertificate, downloadCertificate } from "src/api/backend"; -import { Button, LoadingPage } from "src/components"; +import { Button, HasPermission, LoadingPage } from "src/components"; import { useCertificates } from "src/hooks"; import { T } from "src/locale"; import { @@ -13,6 +13,7 @@ import { showHTTPCertificateModal, showRenewCertificateModal, } from "src/modals"; +import { CERTIFICATES, MANAGE } from "src/modules/Permissions"; import { showError, showObjectSuccess } from "src/notifications"; import Table from "./Table"; @@ -70,7 +71,6 @@ export default function TableWrapper() {
    -
    diff --git a/frontend/src/pages/Certificates/index.tsx b/frontend/src/pages/Certificates/index.tsx index f667e9af..130fb5a9 100644 --- a/frontend/src/pages/Certificates/index.tsx +++ b/frontend/src/pages/Certificates/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { CERTIFICATES, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const Certificates = () => { return ( - + ); diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 1abee7ba..27a98442 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom"; import { HasPermission } from "src/components"; import { useHostReport } from "src/hooks"; import { T } from "src/locale"; +import { DEAD_HOSTS, PROXY_HOSTS, REDIRECTION_HOSTS, STREAMS, VIEW } from "src/modules/Permissions"; const Dashboard = () => { const { data: hostReport } = useHostReport(); @@ -16,7 +17,7 @@ const Dashboard = () => {
    - + - + - + - +
    - { - e.preventDefault(); - onDisableToggle?.(info.row.original.id, !info.row.original.enabled); - }} - > - - - -
    - { - e.preventDefault(); - onDelete?.(info.row.original.id); - }} - > - - - + + { + e.preventDefault(); + onDisableToggle?.(info.row.original.id, !info.row.original.enabled); + }} + > + + + + ); @@ -146,6 +150,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog onNew={onNew} isFiltered={isFiltered} color="red" + permissionSection={DEAD_HOSTS} /> } /> diff --git a/frontend/src/pages/Nginx/DeadHosts/TableWrapper.tsx b/frontend/src/pages/Nginx/DeadHosts/TableWrapper.tsx index ecbfacca..07dd1318 100644 --- a/frontend/src/pages/Nginx/DeadHosts/TableWrapper.tsx +++ b/frontend/src/pages/Nginx/DeadHosts/TableWrapper.tsx @@ -3,10 +3,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import Alert from "react-bootstrap/Alert"; import { deleteDeadHost, toggleDeadHost } from "src/api/backend"; -import { Button, LoadingPage } from "src/components"; +import { Button, HasPermission, LoadingPage } from "src/components"; import { useDeadHosts } from "src/hooks"; import { T } from "src/locale"; import { showDeadHostModal, showDeleteConfirmModal, showHelpModal } from "src/modals"; +import { DEAD_HOSTS, MANAGE } from "src/modules/Permissions"; import { showObjectSuccess } from "src/notifications"; import Table from "./Table"; @@ -76,11 +77,13 @@ export default function TableWrapper() { - {data?.length ? ( - - ) : null} + + {data?.length ? ( + + ) : null} +
    diff --git a/frontend/src/pages/Nginx/DeadHosts/index.tsx b/frontend/src/pages/Nginx/DeadHosts/index.tsx index 99693045..0464b7a6 100644 --- a/frontend/src/pages/Nginx/DeadHosts/index.tsx +++ b/frontend/src/pages/Nginx/DeadHosts/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { DEAD_HOSTS, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const DeadHosts = () => { return ( - + ); diff --git a/frontend/src/pages/Nginx/ProxyHosts/Table.tsx b/frontend/src/pages/Nginx/ProxyHosts/Table.tsx index fa9b62f3..cfbd29f6 100644 --- a/frontend/src/pages/Nginx/ProxyHosts/Table.tsx +++ b/frontend/src/pages/Nginx/ProxyHosts/Table.tsx @@ -8,10 +8,12 @@ import { DomainsFormatter, EmptyData, GravatarFormatter, + HasPermission, TrueFalseFormatter, } from "src/components"; import { TableLayout } from "src/components/Table/TableLayout"; import { intl, T } from "src/locale"; +import { MANAGE, PROXY_HOSTS } from "src/modules/Permissions"; interface Props { data: ProxyHost[]; @@ -105,29 +107,31 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog - { - e.preventDefault(); - onDisableToggle?.(info.row.original.id, !info.row.original.enabled); - }} - > - - - -
    - { - e.preventDefault(); - onDelete?.(info.row.original.id); - }} - > - - - + + { + e.preventDefault(); + onDisableToggle?.(info.row.original.id, !info.row.original.enabled); + }} + > + + + + ); @@ -162,6 +166,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog onNew={onNew} isFiltered={isFiltered} color="lime" + permissionSection={PROXY_HOSTS} /> } /> diff --git a/frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx b/frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx index 1584990f..68af43e1 100644 --- a/frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx +++ b/frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx @@ -3,10 +3,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import Alert from "react-bootstrap/Alert"; import { deleteProxyHost, toggleProxyHost } from "src/api/backend"; -import { Button, LoadingPage } from "src/components"; +import { Button, HasPermission, LoadingPage } from "src/components"; import { useProxyHosts } from "src/hooks"; import { T } from "src/locale"; import { showDeleteConfirmModal, showHelpModal, showProxyHostModal } from "src/modals"; +import { MANAGE, PROXY_HOSTS } from "src/modules/Permissions"; import { showObjectSuccess } from "src/notifications"; import Table from "./Table"; @@ -59,7 +60,6 @@ export default function TableWrapper() {
    -
    {data?.length ? ( @@ -79,11 +79,17 @@ export default function TableWrapper() { - {data?.length ? ( - - ) : null} + + {data?.length ? ( + + ) : null} +
    diff --git a/frontend/src/pages/Nginx/ProxyHosts/index.tsx b/frontend/src/pages/Nginx/ProxyHosts/index.tsx index 80a8fd09..d20658e1 100644 --- a/frontend/src/pages/Nginx/ProxyHosts/index.tsx +++ b/frontend/src/pages/Nginx/ProxyHosts/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { PROXY_HOSTS, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const ProxyHosts = () => { return ( - + ); diff --git a/frontend/src/pages/Nginx/RedirectionHosts/Table.tsx b/frontend/src/pages/Nginx/RedirectionHosts/Table.tsx index 51e62d66..ece00bd6 100644 --- a/frontend/src/pages/Nginx/RedirectionHosts/Table.tsx +++ b/frontend/src/pages/Nginx/RedirectionHosts/Table.tsx @@ -7,10 +7,12 @@ import { DomainsFormatter, EmptyData, GravatarFormatter, + HasPermission, TrueFalseFormatter, } from "src/components"; import { TableLayout } from "src/components/Table/TableLayout"; import { intl, T } from "src/locale"; +import { MANAGE, REDIRECTION_HOSTS } from "src/modules/Permissions"; interface Props { data: RedirectionHost[]; @@ -110,29 +112,31 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog - { - e.preventDefault(); - onDisableToggle?.(info.row.original.id, !info.row.original.enabled); - }} - > - - - -
    - { - e.preventDefault(); - onDelete?.(info.row.original.id); - }} - > - - - + + { + e.preventDefault(); + onDisableToggle?.(info.row.original.id, !info.row.original.enabled); + }} + > + + + + ); @@ -167,6 +171,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog onNew={onNew} isFiltered={isFiltered} color="yellow" + permissionSection={REDIRECTION_HOSTS} /> } /> diff --git a/frontend/src/pages/Nginx/RedirectionHosts/TableWrapper.tsx b/frontend/src/pages/Nginx/RedirectionHosts/TableWrapper.tsx index cba7d5b9..382b7336 100644 --- a/frontend/src/pages/Nginx/RedirectionHosts/TableWrapper.tsx +++ b/frontend/src/pages/Nginx/RedirectionHosts/TableWrapper.tsx @@ -3,10 +3,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import Alert from "react-bootstrap/Alert"; import { deleteRedirectionHost, toggleRedirectionHost } from "src/api/backend"; -import { Button, LoadingPage } from "src/components"; +import { Button, HasPermission, LoadingPage } from "src/components"; import { useRedirectionHosts } from "src/hooks"; import { T } from "src/locale"; import { showDeleteConfirmModal, showHelpModal, showRedirectionHostModal } from "src/modals"; +import { MANAGE, REDIRECTION_HOSTS } from "src/modules/Permissions"; import { showObjectSuccess } from "src/notifications"; import Table from "./Table"; @@ -59,7 +60,6 @@ export default function TableWrapper() {
    -
    {data?.length ? ( @@ -79,15 +79,17 @@ export default function TableWrapper() { - {data?.length ? ( - - ) : null} + + {data?.length ? ( + + ) : null} +
    diff --git a/frontend/src/pages/Nginx/RedirectionHosts/index.tsx b/frontend/src/pages/Nginx/RedirectionHosts/index.tsx index 3df72827..32bf2441 100644 --- a/frontend/src/pages/Nginx/RedirectionHosts/index.tsx +++ b/frontend/src/pages/Nginx/RedirectionHosts/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { REDIRECTION_HOSTS, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const RedirectionHosts = () => { return ( - + ); diff --git a/frontend/src/pages/Nginx/Streams/Table.tsx b/frontend/src/pages/Nginx/Streams/Table.tsx index 7aa53293..b7246565 100644 --- a/frontend/src/pages/Nginx/Streams/Table.tsx +++ b/frontend/src/pages/Nginx/Streams/Table.tsx @@ -6,11 +6,13 @@ import { CertificateFormatter, EmptyData, GravatarFormatter, + HasPermission, TrueFalseFormatter, ValueWithDateFormatter, } from "src/components"; import { TableLayout } from "src/components/Table/TableLayout"; import { intl, T } from "src/locale"; +import { MANAGE, STREAMS } from "src/modules/Permissions"; interface Props { data: Stream[]; @@ -118,29 +120,31 @@ export default function Table({ data, isFetching, isFiltered, onEdit, onDelete, - { - e.preventDefault(); - onDisableToggle?.(info.row.original.id, !info.row.original.enabled); - }} - > - - - -
    - { - e.preventDefault(); - onDelete?.(info.row.original.id); - }} - > - - - + + { + e.preventDefault(); + onDisableToggle?.(info.row.original.id, !info.row.original.enabled); + }} + > + + + + ); @@ -175,6 +179,7 @@ export default function Table({ data, isFetching, isFiltered, onEdit, onDelete, onNew={onNew} isFiltered={isFiltered} color="blue" + permissionSection={STREAMS} /> } /> diff --git a/frontend/src/pages/Nginx/Streams/TableWrapper.tsx b/frontend/src/pages/Nginx/Streams/TableWrapper.tsx index ecb8f6ec..ec9a8d40 100644 --- a/frontend/src/pages/Nginx/Streams/TableWrapper.tsx +++ b/frontend/src/pages/Nginx/Streams/TableWrapper.tsx @@ -3,10 +3,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import Alert from "react-bootstrap/Alert"; import { deleteStream, toggleStream } from "src/api/backend"; -import { Button, LoadingPage } from "src/components"; +import { Button, HasPermission, LoadingPage } from "src/components"; import { useStreams } from "src/hooks"; import { T } from "src/locale"; import { showDeleteConfirmModal, showHelpModal, showStreamModal } from "src/modals"; +import { MANAGE, STREAMS } from "src/modules/Permissions"; import { showObjectSuccess } from "src/notifications"; import Table from "./Table"; @@ -61,7 +62,6 @@ export default function TableWrapper() {
    -
    {data?.length ? ( @@ -81,11 +81,13 @@ export default function TableWrapper() { - {data?.length ? ( - - ) : null} + + {data?.length ? ( + + ) : null} +
    diff --git a/frontend/src/pages/Nginx/Streams/index.tsx b/frontend/src/pages/Nginx/Streams/index.tsx index c997ea69..31c4f636 100644 --- a/frontend/src/pages/Nginx/Streams/index.tsx +++ b/frontend/src/pages/Nginx/Streams/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { STREAMS, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const Streams = () => { return ( - + ); diff --git a/frontend/src/pages/Settings/index.tsx b/frontend/src/pages/Settings/index.tsx index dccfb910..7904cbc0 100644 --- a/frontend/src/pages/Settings/index.tsx +++ b/frontend/src/pages/Settings/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { ADMIN, VIEW } from "src/modules/Permissions"; import Layout from "./Layout"; const Settings = () => { return ( - + ); diff --git a/frontend/src/pages/Users/index.tsx b/frontend/src/pages/Users/index.tsx index 3f20b165..53b43664 100644 --- a/frontend/src/pages/Users/index.tsx +++ b/frontend/src/pages/Users/index.tsx @@ -1,9 +1,10 @@ import { HasPermission } from "src/components"; +import { ADMIN, VIEW } from "src/modules/Permissions"; import TableWrapper from "./TableWrapper"; const Users = () => { return ( - + );