mirror of
https://github.com/portainer/portainer.git
synced 2025-07-22 23:09:41 +02:00
fix(container): hide capabilities tab EE-6258 (#10540)
This commit is contained in:
parent
403fdf7ce3
commit
3964852fda
5 changed files with 58 additions and 34 deletions
|
@ -7,6 +7,7 @@ export interface Option<T extends string | number = string> {
|
||||||
label: ReactNode;
|
label: ReactNode;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
id: T;
|
id: T;
|
||||||
|
hidden?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props<T extends string | number> {
|
interface Props<T extends string | number> {
|
||||||
|
@ -33,31 +34,34 @@ export function NavTabs<T extends string | number = string>({
|
||||||
<ul
|
<ul
|
||||||
className={clsx('nav', `nav-${type}`, { 'nav-justified': justified })}
|
className={clsx('nav', `nav-${type}`, { 'nav-justified': justified })}
|
||||||
>
|
>
|
||||||
{options.map((option) => (
|
{options.map(
|
||||||
<li
|
(option) =>
|
||||||
className={clsx({
|
!option.hidden && (
|
||||||
active: option.id === selectedId,
|
<li
|
||||||
[styles.parent]: !option.children,
|
className={clsx({
|
||||||
disabled,
|
active: option.id === selectedId,
|
||||||
})}
|
[styles.parent]: !option.children,
|
||||||
key={option.id}
|
disabled,
|
||||||
>
|
})}
|
||||||
{/* rule disabled because `nav-tabs` requires an anchor */}
|
key={option.id}
|
||||||
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
|
>
|
||||||
<a
|
{/* rule disabled because `nav-tabs` requires an anchor */}
|
||||||
onClick={() => handleSelect(option)}
|
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
|
||||||
onKeyDown={(e) => {
|
<a
|
||||||
if (e.key === 'Enter' || e.key === ' ') {
|
onClick={() => handleSelect(option)}
|
||||||
handleSelect(option);
|
onKeyDown={(e) => {
|
||||||
}
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
}}
|
handleSelect(option);
|
||||||
role="button"
|
}
|
||||||
tabIndex={0}
|
}}
|
||||||
>
|
role="button"
|
||||||
{option.label}
|
tabIndex={0}
|
||||||
</a>
|
>
|
||||||
</li>
|
{option.label}
|
||||||
))}
|
</a>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
{selected && selected.children && (
|
{selected && selected.children && (
|
||||||
<div className="tab-content mt-3">{selected.children}</div>
|
<div className="tab-content mt-3">{selected.children}</div>
|
||||||
|
|
|
@ -5,16 +5,19 @@ import { Values } from './CapabilitiesTab';
|
||||||
|
|
||||||
export function toRequest(
|
export function toRequest(
|
||||||
oldConfig: CreateContainerRequest,
|
oldConfig: CreateContainerRequest,
|
||||||
values: Values
|
values: Values,
|
||||||
|
hideCapabilities: boolean
|
||||||
): CreateContainerRequest {
|
): CreateContainerRequest {
|
||||||
return {
|
return {
|
||||||
...oldConfig,
|
...oldConfig,
|
||||||
HostConfig: {
|
HostConfig: {
|
||||||
...oldConfig.HostConfig,
|
...oldConfig.HostConfig,
|
||||||
CapAdd: values,
|
CapAdd: hideCapabilities ? [] : values,
|
||||||
CapDrop: capabilities
|
CapDrop: hideCapabilities
|
||||||
.filter((cap) => !values.includes(cap.key))
|
? []
|
||||||
.map((cap) => cap.key),
|
: capabilities
|
||||||
|
.filter((cap) => !values.includes(cap.key))
|
||||||
|
.map((cap) => cap.key),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Formik } from 'formik';
|
||||||
import { useRouter } from '@uirouter/react';
|
import { useRouter } from '@uirouter/react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { useCurrentUser } from '@/react/hooks/useUser';
|
import { useCurrentUser, useIsEnvironmentAdmin } from '@/react/hooks/useUser';
|
||||||
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
||||||
import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment';
|
import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment';
|
||||||
import { useEnvironmentRegistries } from '@/react/portainer/environments/queries/useEnvironmentRegistries';
|
import { useEnvironmentRegistries } from '@/react/portainer/environments/queries/useEnvironmentRegistries';
|
||||||
|
@ -48,6 +48,7 @@ function CreateForm() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { trackEvent } = useAnalytics();
|
const { trackEvent } = useAnalytics();
|
||||||
const { isAdmin } = useCurrentUser();
|
const { isAdmin } = useCurrentUser();
|
||||||
|
const isEnvironmentAdmin = useIsEnvironmentAdmin();
|
||||||
const [isDockerhubRateLimited, setIsDockerhubRateLimited] = useState(false);
|
const [isDockerhubRateLimited, setIsDockerhubRateLimited] = useState(false);
|
||||||
|
|
||||||
const mutation = useCreateOrReplaceMutation();
|
const mutation = useCreateOrReplaceMutation();
|
||||||
|
@ -79,6 +80,10 @@ function CreateForm() {
|
||||||
|
|
||||||
const environment = envQuery.data;
|
const environment = envQuery.data;
|
||||||
|
|
||||||
|
const hideCapabilities =
|
||||||
|
!environment.SecuritySettings.allowContainerCapabilitiesForRegularUsers &&
|
||||||
|
!isEnvironmentAdmin;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isDuplicating = false,
|
isDuplicating = false,
|
||||||
initialValues,
|
initialValues,
|
||||||
|
@ -112,6 +117,7 @@ function CreateForm() {
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
>
|
>
|
||||||
<InnerForm
|
<InnerForm
|
||||||
|
hideCapabilities={hideCapabilities}
|
||||||
onChangeName={syncName}
|
onChangeName={syncName}
|
||||||
isDuplicate={isDuplicating}
|
isDuplicate={isDuplicating}
|
||||||
isLoading={mutation.isLoading}
|
isLoading={mutation.isLoading}
|
||||||
|
@ -136,7 +142,7 @@ function CreateForm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const registry = getRegistry(values.image, registriesQuery.data || []);
|
const registry = getRegistry(values.image, registriesQuery.data || []);
|
||||||
const config = toRequest(values, registry);
|
const config = toRequest(values, registry, hideCapabilities);
|
||||||
|
|
||||||
mutation.mutate(
|
mutation.mutate(
|
||||||
{ config, environment, values, registry, oldContainer, extraNetworks },
|
{ config, environment, values, registry, oldContainer, extraNetworks },
|
||||||
|
|
|
@ -24,11 +24,13 @@ import { EnvVarsTab } from './EnvVarsTab';
|
||||||
import { EditResourcesForm } from './ResourcesTab/EditResourceForm';
|
import { EditResourcesForm } from './ResourcesTab/EditResourceForm';
|
||||||
|
|
||||||
export function InnerForm({
|
export function InnerForm({
|
||||||
|
hideCapabilities = false,
|
||||||
isLoading,
|
isLoading,
|
||||||
isDuplicate,
|
isDuplicate,
|
||||||
onChangeName,
|
onChangeName,
|
||||||
onRateLimit,
|
onRateLimit,
|
||||||
}: {
|
}: {
|
||||||
|
hideCapabilities: boolean;
|
||||||
isDuplicate: boolean;
|
isDuplicate: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
onChangeName: (value: string) => void;
|
onChangeName: (value: string) => void;
|
||||||
|
@ -202,6 +204,7 @@ export function InnerForm({
|
||||||
{
|
{
|
||||||
id: 'capabilities',
|
id: 'capabilities',
|
||||||
label: 'Capabilities',
|
label: 'Capabilities',
|
||||||
|
hidden: hideCapabilities,
|
||||||
children: (
|
children: (
|
||||||
<CapabilitiesTab
|
<CapabilitiesTab
|
||||||
values={values.capabilities}
|
values={values.capabilities}
|
||||||
|
|
|
@ -13,7 +13,11 @@ import { restartPolicyTabUtils } from './RestartPolicyTab';
|
||||||
import { envVarsTabUtils } from './EnvVarsTab';
|
import { envVarsTabUtils } from './EnvVarsTab';
|
||||||
import { Values } from './useInitialValues';
|
import { Values } from './useInitialValues';
|
||||||
|
|
||||||
export function toRequest(values: Values, registry?: Registry) {
|
export function toRequest(
|
||||||
|
values: Values,
|
||||||
|
registry?: Registry,
|
||||||
|
ignoreCapabilities?: boolean
|
||||||
|
) {
|
||||||
let config: CreateContainerRequest = {
|
let config: CreateContainerRequest = {
|
||||||
HostConfig: {},
|
HostConfig: {},
|
||||||
NetworkingConfig: {},
|
NetworkingConfig: {},
|
||||||
|
@ -25,7 +29,11 @@ export function toRequest(values: Values, registry?: Registry) {
|
||||||
config = labelsTabUtils.toRequest(config, values.labels);
|
config = labelsTabUtils.toRequest(config, values.labels);
|
||||||
config = restartPolicyTabUtils.toRequest(config, values.restartPolicy);
|
config = restartPolicyTabUtils.toRequest(config, values.restartPolicy);
|
||||||
config = resourcesTabUtils.toRequest(config, values.resources);
|
config = resourcesTabUtils.toRequest(config, values.resources);
|
||||||
config = capabilitiesTabUtils.toRequest(config, values.capabilities);
|
config = capabilitiesTabUtils.toRequest(
|
||||||
|
config,
|
||||||
|
values.capabilities,
|
||||||
|
!!ignoreCapabilities
|
||||||
|
);
|
||||||
config = baseFormUtils.toRequest(config, values);
|
config = baseFormUtils.toRequest(config, values);
|
||||||
config = envVarsTabUtils.toRequest(config, values.env);
|
config = envVarsTabUtils.toRequest(config, values.env);
|
||||||
config.Image = buildImageFullURI(values.image.image, registry);
|
config.Image = buildImageFullURI(values.image.image, registry);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue