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