1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 13:55:21 +02:00

fix(apikey): don't authenticate api key for external auth [EE-6932] (#11460)
Some checks are pending
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run

This commit is contained in:
Matt Hook 2024-04-08 11:03:52 +12:00 committed by GitHub
parent a3c7eb0ce0
commit dc9d7ae3f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 88 additions and 30 deletions

View file

@ -2,11 +2,22 @@ import { SchemaOf, object, string } from 'yup';
import { ApiKeyFormValues } from './types';
export function getAPITokenValidationSchema(): SchemaOf<ApiKeyFormValues> {
export function getAPITokenValidationSchema(
requirePassword: boolean
): SchemaOf<ApiKeyFormValues> {
if (requirePassword) {
return object({
password: string().required('Password is required.'),
description: string()
.max(128, 'Description must be at most 128 characters')
.required('Description is required.'),
});
}
return object({
password: string().required('Password is required.'),
password: string().optional(),
description: string()
.max(128, 'Description must be at most 128 characters')
.required('Description is required'),
.required('Description is required.'),
});
}

View file

@ -33,7 +33,10 @@ test('the button is disabled when all fields are blank and enabled when all fiel
});
function renderComponent() {
const user = new UserViewModel({ Username: 'user' });
const user = new UserViewModel({
Username: 'admin',
Id: 1,
});
const Wrapped = withTestQueryProvider(
withUserProvider(withTestRouter(CreateUserAccessToken), user)

View file

@ -3,10 +3,13 @@ import { useState } from 'react';
import { useCurrentUser } from '@/react/hooks/useUser';
import { useAnalytics } from '@/react/hooks/useAnalytics';
import { AuthenticationMethod } from '@/react/portainer/settings/types';
import { Widget } from '@@/Widget';
import { PageHeader } from '@@/PageHeader';
import { usePublicSettings } from '../../settings/queries/usePublicSettings';
import { ApiKeyFormValues } from './types';
import { getAPITokenValidationSchema } from './CreateUserAcccessToken.validation';
import { useCreateUserAccessTokenMutation } from './useCreateUserAccessTokenMutation';
@ -23,6 +26,11 @@ export function CreateUserAccessToken() {
const { user } = useCurrentUser();
const [newAPIToken, setNewAPIToken] = useState('');
const { trackEvent } = useAnalytics();
const settings = usePublicSettings();
const requirePassword =
settings.data?.AuthenticationMethod === AuthenticationMethod.Internal ||
user.Id === 1;
return (
<>
@ -43,12 +51,16 @@ export function CreateUserAccessToken() {
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={getAPITokenValidationSchema}
validationSchema={getAPITokenValidationSchema(
requirePassword
)}
>
<CreateUserAccessTokenInnerForm />
<CreateUserAccessTokenInnerForm
showAuthentication={requirePassword}
/>
</Formik>
) : (
DisplayUserAccessToken(newAPIToken)
<DisplayUserAccessToken apikey={newAPIToken} />
)}
</Widget.Body>
</Widget>

View file

@ -6,7 +6,11 @@ import { LoadingButton } from '@@/buttons';
import { ApiKeyFormValues } from './types';
export function CreateUserAccessTokenInnerForm() {
interface Props {
showAuthentication: boolean;
}
export function CreateUserAccessTokenInnerForm({ showAuthentication }: Props) {
const { errors, values, handleSubmit, isValid, dirty } =
useFormikContext<ApiKeyFormValues>();
@ -16,21 +20,23 @@ export function CreateUserAccessTokenInnerForm() {
onSubmit={handleSubmit}
autoComplete="off"
>
<FormControl
inputId="password"
label="Current password"
required
errors={errors.password}
>
<Field
as={Input}
type="password"
id="password"
name="password"
value={values.password}
autoComplete="new-password"
/>
</FormControl>
{showAuthentication && (
<FormControl
inputId="password"
label="Current password"
required
errors={errors.password}
>
<Field
as={Input}
type="password"
id="password"
name="password"
value={values.password}
autoComplete="new-password"
/>
</FormControl>
)}
<FormControl
inputId="description"
label="Description"

View file

@ -4,7 +4,7 @@ import { Button, CopyButton } from '@@/buttons';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { TextTip } from '@@/Tip/TextTip';
export function DisplayUserAccessToken(apikey: string) {
export function DisplayUserAccessToken({ apikey }: { apikey: string }) {
const router = useRouter();
return (
<>

View file

@ -1,4 +1,4 @@
export interface ApiKeyFormValues {
password: string;
password?: string;
description: string;
}