1
0
mirror of https://github.com/NginxProxyManager/nginx-proxy-manager.git synced 2025-11-05 15:30:37 +03:00

Permissions polish for restricted users

This commit is contained in:
Jamie Curnow
2025-10-30 19:01:00 +10:00
parent 74a8c5d806
commit 4709f9826c
28 changed files with 457 additions and 306 deletions

View File

@@ -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 { DEAD_HOSTS, MANAGE } from "src/modules/Permissions";
interface Props {
data: DeadHost[];
@@ -89,29 +91,31 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog
<IconEdit size={16} />
<T id="action.edit" />
</a>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id={info.row.original.enabled ? "action.disable" : "action.enable"} />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
<HasPermission section={DEAD_HOSTS} permission={MANAGE} hideError>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id={info.row.original.enabled ? "action.disable" : "action.enable"} />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
</HasPermission>
</div>
</span>
);
@@ -146,6 +150,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog
onNew={onNew}
isFiltered={isFiltered}
color="red"
permissionSection={DEAD_HOSTS}
/>
}
/>

View File

@@ -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() {
<Button size="sm" onClick={() => showHelpModal("DeadHosts", "red")}>
<IconHelp size={20} />
</Button>
{data?.length ? (
<Button size="sm" className="btn-red" onClick={() => showDeadHostModal("new")}>
<T id="object.add" tData={{ object: "dead-host" }} />
</Button>
) : null}
<HasPermission section={DEAD_HOSTS} permission={MANAGE} hideError>
{data?.length ? (
<Button size="sm" className="btn-red" onClick={() => showDeadHostModal("new")}>
<T id="object.add" tData={{ object: "dead-host" }} />
</Button>
) : null}
</HasPermission>
</div>
</div>
</div>

View File

@@ -1,9 +1,10 @@
import { HasPermission } from "src/components";
import { DEAD_HOSTS, VIEW } from "src/modules/Permissions";
import TableWrapper from "./TableWrapper";
const DeadHosts = () => {
return (
<HasPermission permission="deadHosts" type="view" pageLoading loadingNoLogo>
<HasPermission section={DEAD_HOSTS} permission={VIEW} pageLoading loadingNoLogo>
<TableWrapper />
</HasPermission>
);

View File

@@ -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
<IconEdit size={16} />
<T id="action.edit" />
</a>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id={info.row.original.enabled ? "action.disable" : "action.enable"} />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
<HasPermission section={PROXY_HOSTS} permission={MANAGE} hideError>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id={info.row.original.enabled ? "action.disable" : "action.enable"} />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
</HasPermission>
</div>
</span>
);
@@ -162,6 +166,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog
onNew={onNew}
isFiltered={isFiltered}
color="lime"
permissionSection={PROXY_HOSTS}
/>
}
/>

View File

@@ -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() {
<T id="proxy-hosts" />
</h2>
</div>
<div className="col-md-auto col-sm-12">
<div className="ms-auto d-flex flex-wrap btn-list">
{data?.length ? (
@@ -79,11 +79,17 @@ export default function TableWrapper() {
<Button size="sm" onClick={() => showHelpModal("ProxyHosts", "lime")}>
<IconHelp size={20} />
</Button>
{data?.length ? (
<Button size="sm" className="btn-lime" onClick={() => showProxyHostModal("new")}>
<T id="object.add" tData={{ object: "proxy-host" }} />
</Button>
) : null}
<HasPermission section={PROXY_HOSTS} permission={MANAGE} hideError>
{data?.length ? (
<Button
size="sm"
className="btn-lime"
onClick={() => showProxyHostModal("new")}
>
<T id="object.add" tData={{ object: "proxy-host" }} />
</Button>
) : null}
</HasPermission>
</div>
</div>
</div>

View File

@@ -1,9 +1,10 @@
import { HasPermission } from "src/components";
import { PROXY_HOSTS, VIEW } from "src/modules/Permissions";
import TableWrapper from "./TableWrapper";
const ProxyHosts = () => {
return (
<HasPermission permission="proxyHosts" type="view" pageLoading loadingNoLogo>
<HasPermission section={PROXY_HOSTS} permission={VIEW} pageLoading loadingNoLogo>
<TableWrapper />
</HasPermission>
);

View File

@@ -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
<IconEdit size={16} />
<T id="action.edit" />
</a>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id={info.row.original.enabled ? "action.disable" : "action.enable"} />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
<HasPermission section={REDIRECTION_HOSTS} permission={MANAGE} hideError>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id={info.row.original.enabled ? "action.disable" : "action.enable"} />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
</HasPermission>
</div>
</span>
);
@@ -167,6 +171,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog
onNew={onNew}
isFiltered={isFiltered}
color="yellow"
permissionSection={REDIRECTION_HOSTS}
/>
}
/>

View File

@@ -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() {
<T id="redirection-hosts" />
</h2>
</div>
<div className="col-md-auto col-sm-12">
<div className="ms-auto d-flex flex-wrap btn-list">
{data?.length ? (
@@ -79,15 +79,17 @@ export default function TableWrapper() {
<Button size="sm" onClick={() => showHelpModal("RedirectionHosts", "yellow")}>
<IconHelp size={20} />
</Button>
{data?.length ? (
<Button
size="sm"
className="btn-yellow"
onClick={() => showRedirectionHostModal("new")}
>
<T id="object.add" tData={{ object: "redirection-host" }} />
</Button>
) : null}
<HasPermission section={REDIRECTION_HOSTS} permission={MANAGE} hideError>
{data?.length ? (
<Button
size="sm"
className="btn-yellow"
onClick={() => showRedirectionHostModal("new")}
>
<T id="object.add" tData={{ object: "redirection-host" }} />
</Button>
) : null}
</HasPermission>
</div>
</div>
</div>

View File

@@ -1,9 +1,10 @@
import { HasPermission } from "src/components";
import { REDIRECTION_HOSTS, VIEW } from "src/modules/Permissions";
import TableWrapper from "./TableWrapper";
const RedirectionHosts = () => {
return (
<HasPermission permission="redirectionHosts" type="view" pageLoading loadingNoLogo>
<HasPermission section={REDIRECTION_HOSTS} permission={VIEW} pageLoading loadingNoLogo>
<TableWrapper />
</HasPermission>
);

View File

@@ -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,
<IconEdit size={16} />
<T id="action.edit" />
</a>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id="action.disable" />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
<HasPermission section={STREAMS} permission={MANAGE} hideError>
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
}}
>
<IconPower size={16} />
<T id="action.disable" />
</a>
<div className="dropdown-divider" />
<a
className="dropdown-item"
href="#"
onClick={(e) => {
e.preventDefault();
onDelete?.(info.row.original.id);
}}
>
<IconTrash size={16} />
<T id="action.delete" />
</a>
</HasPermission>
</div>
</span>
);
@@ -175,6 +179,7 @@ export default function Table({ data, isFetching, isFiltered, onEdit, onDelete,
onNew={onNew}
isFiltered={isFiltered}
color="blue"
permissionSection={STREAMS}
/>
}
/>

View File

@@ -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() {
<T id="streams" />
</h2>
</div>
<div className="col-md-auto col-sm-12">
<div className="ms-auto d-flex flex-wrap btn-list">
{data?.length ? (
@@ -81,11 +81,13 @@ export default function TableWrapper() {
<Button size="sm" onClick={() => showHelpModal("Streams", "blue")}>
<IconHelp size={20} />
</Button>
{data?.length ? (
<Button size="sm" className="btn-blue" onClick={() => showStreamModal("new")}>
<T id="object.add" tData={{ object: "stream" }} />
</Button>
) : null}
<HasPermission section={STREAMS} permission={MANAGE} hideError>
{data?.length ? (
<Button size="sm" className="btn-blue" onClick={() => showStreamModal("new")}>
<T id="object.add" tData={{ object: "stream" }} />
</Button>
) : null}
</HasPermission>
</div>
</div>
</div>

View File

@@ -1,9 +1,10 @@
import { HasPermission } from "src/components";
import { STREAMS, VIEW } from "src/modules/Permissions";
import TableWrapper from "./TableWrapper";
const Streams = () => {
return (
<HasPermission permission="streams" type="view" pageLoading loadingNoLogo>
<HasPermission section={STREAMS} permission={VIEW} pageLoading loadingNoLogo>
<TableWrapper />
</HasPermission>
);