💄(oidc) add login page in the frontend
To have a better user experience, we want the login page to in the frontend.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { Loader } from '@openfun/cunningham-react';
|
import { Loader } from '@openfun/cunningham-react';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
import { PropsWithChildren, useEffect } from 'react';
|
import { PropsWithChildren, useEffect } from 'react';
|
||||||
|
|
||||||
import { Box } from '@/components';
|
import { Box } from '@/components';
|
||||||
@@ -7,12 +8,16 @@ import { useAuthStore } from './useAuthStore';
|
|||||||
|
|
||||||
export const Auth = ({ children }: PropsWithChildren) => {
|
export const Auth = ({ children }: PropsWithChildren) => {
|
||||||
const { authenticated, initAuth } = useAuthStore();
|
const { authenticated, initAuth } = useAuthStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const isLoginPage = router.pathname === '/login';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initAuth();
|
if (!isLoginPage) {
|
||||||
}, [initAuth]);
|
initAuth();
|
||||||
|
}
|
||||||
|
}, [initAuth, isLoginPage]);
|
||||||
|
|
||||||
if (!authenticated) {
|
if (!authenticated && !isLoginPage) {
|
||||||
return (
|
return (
|
||||||
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
|
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
|
||||||
<Loader />
|
<Loader />
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
|
||||||
|
import { AppWrapper } from '@/tests/utils';
|
||||||
|
|
||||||
|
import { InputUserEmail } from '../components/InputUserEmail';
|
||||||
|
|
||||||
|
describe('InputUserEmail', () => {
|
||||||
|
const mockSetEmail = jest.fn();
|
||||||
|
const defaultProps = {
|
||||||
|
label: 'Email Address',
|
||||||
|
email: '',
|
||||||
|
setEmail: mockSetEmail,
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderInput = (props = defaultProps) => {
|
||||||
|
render(<InputUserEmail {...props} />, { wrapper: AppWrapper });
|
||||||
|
};
|
||||||
|
|
||||||
|
it('renders the email input with correct label', () => {
|
||||||
|
renderInput();
|
||||||
|
expect(screen.getByLabelText('Email Address')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls setEmail when input value changes', async () => {
|
||||||
|
renderInput();
|
||||||
|
const input = screen.getByLabelText('Email Address');
|
||||||
|
await userEvent.type(input, 'test@example.com');
|
||||||
|
expect(mockSetEmail).toHaveBeenCalledWith('test@example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays the current email value', () => {
|
||||||
|
renderInput({ ...defaultProps, email: 'test@example.com' });
|
||||||
|
const input: HTMLInputElement = screen.getByLabelText('Email Address');
|
||||||
|
expect(input.value).toBe('test@example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has required attribute', () => {
|
||||||
|
renderInput();
|
||||||
|
const input = screen.getByLabelText('Email Address');
|
||||||
|
expect(input).toHaveAttribute('required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct type and autocomplete attributes', () => {
|
||||||
|
renderInput();
|
||||||
|
const input = screen.getByLabelText('Email Address');
|
||||||
|
expect(input).toHaveAttribute('type', 'email');
|
||||||
|
expect(input).toHaveAttribute('autocomplete', 'username');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
|
||||||
|
import { AppWrapper } from '@/tests/utils';
|
||||||
|
|
||||||
|
import { InputUserPassword } from '../components/InputUserPassword';
|
||||||
|
|
||||||
|
describe('InputUserPassword', () => {
|
||||||
|
const mockSetPassword = jest.fn();
|
||||||
|
const defaultProps = {
|
||||||
|
label: 'Password',
|
||||||
|
setPassword: mockSetPassword,
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderInput = (props = defaultProps) => {
|
||||||
|
render(<InputUserPassword {...props} />, { wrapper: AppWrapper });
|
||||||
|
};
|
||||||
|
|
||||||
|
it('renders the password input with correct label', () => {
|
||||||
|
renderInput();
|
||||||
|
expect(screen.getByLabelText('Password')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls setPassword when input value changes', async () => {
|
||||||
|
renderInput();
|
||||||
|
const input = screen.getByLabelText('Password');
|
||||||
|
await userEvent.type(input, 'mypassword123');
|
||||||
|
expect(mockSetPassword).toHaveBeenCalledWith('mypassword123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has required attribute', () => {
|
||||||
|
renderInput();
|
||||||
|
const input = screen.getByLabelText('Password');
|
||||||
|
expect(input).toHaveAttribute('required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct type and autocomplete attributes', () => {
|
||||||
|
renderInput();
|
||||||
|
const input = screen.getByLabelText('Password');
|
||||||
|
expect(input).toHaveAttribute('type', 'password');
|
||||||
|
expect(input).toHaveAttribute('autocomplete', 'current-password');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
|
||||||
|
import { AppWrapper } from '@/tests/utils';
|
||||||
|
|
||||||
|
import { LoginForm } from '../components/LoginForm';
|
||||||
|
|
||||||
|
jest.mock('next/navigation', () => ({
|
||||||
|
useRouter: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('next/router', () => ({
|
||||||
|
useRouter: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('LoginForm', () => {
|
||||||
|
const mockHandleSubmit = jest.fn((e) => e.preventDefault());
|
||||||
|
const mockSetEmail = jest.fn();
|
||||||
|
const mockSetPassword = jest.fn();
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
title: 'Login',
|
||||||
|
labelEmail: 'Email',
|
||||||
|
labelPassword: 'Password',
|
||||||
|
labelSignIn: 'Sign In',
|
||||||
|
email: '',
|
||||||
|
setEmail: mockSetEmail,
|
||||||
|
setPassword: mockSetPassword,
|
||||||
|
error: '',
|
||||||
|
handleSubmit: mockHandleSubmit,
|
||||||
|
blockingError: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderLoginForm = () => {
|
||||||
|
render(<LoginForm {...defaultProps} />, { wrapper: AppWrapper });
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should render the login form', async () => {
|
||||||
|
renderLoginForm();
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Login')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByLabelText('Email')).toBeInTheDocument();
|
||||||
|
expect(screen.getByLabelText('Password')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Sign In')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle email input', async () => {
|
||||||
|
renderLoginForm();
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByLabelText('Email')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
const emailInput = screen.getByLabelText('Email');
|
||||||
|
await userEvent.type(emailInput, 'test@example.com');
|
||||||
|
|
||||||
|
expect(mockSetEmail).toHaveBeenCalledWith('test@example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle password input', async () => {
|
||||||
|
renderLoginForm();
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByLabelText('Password')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
const passwordInput = screen.getByLabelText('Password');
|
||||||
|
await userEvent.type(passwordInput, 'password123');
|
||||||
|
|
||||||
|
expect(mockSetPassword).toHaveBeenCalledWith('password123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should submit the form', async () => {
|
||||||
|
renderLoginForm();
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Sign In')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = screen.getByTestId('login-form');
|
||||||
|
fireEvent.submit(form);
|
||||||
|
|
||||||
|
expect(mockHandleSubmit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display error message when provided', async () => {
|
||||||
|
const errorMessage = 'Invalid credentials';
|
||||||
|
render(<LoginForm {...defaultProps} error={errorMessage} />, {
|
||||||
|
wrapper: AppWrapper,
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText(errorMessage)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display blocking error and hide form when provided', async () => {
|
||||||
|
const blockingError = 'Service unavailable';
|
||||||
|
render(<LoginForm {...defaultProps} blockingError={blockingError} />, {
|
||||||
|
wrapper: AppWrapper,
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText(blockingError)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.queryByLabelText('Email')).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByLabelText('Password')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { Input } from '@openfun/cunningham-react';
|
||||||
|
|
||||||
|
interface InputUserEmailProps {
|
||||||
|
label: string;
|
||||||
|
email: string;
|
||||||
|
setEmail: (newEmail: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InputUserEmail = ({
|
||||||
|
label,
|
||||||
|
email,
|
||||||
|
setEmail,
|
||||||
|
}: InputUserEmailProps) => {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
label={label}
|
||||||
|
type="email"
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
fullWidth
|
||||||
|
autoComplete="username"
|
||||||
|
value={email}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Input } from '@openfun/cunningham-react';
|
||||||
|
|
||||||
|
interface InputUserEmailProps {
|
||||||
|
label: string;
|
||||||
|
setPassword: (newEmail: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InputUserPassword = ({
|
||||||
|
label,
|
||||||
|
setPassword,
|
||||||
|
}: InputUserEmailProps) => {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
label={label}
|
||||||
|
type="password"
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
required
|
||||||
|
fullWidth
|
||||||
|
autoComplete="current-password"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { Button } from '@openfun/cunningham-react';
|
||||||
|
|
||||||
|
import { Box, Text } from '@/components';
|
||||||
|
import { InputUserEmail, InputUserPassword } from '@/features/login';
|
||||||
|
|
||||||
|
interface LoginFormProps {
|
||||||
|
title: string;
|
||||||
|
labelEmail: string;
|
||||||
|
labelPassword: string;
|
||||||
|
labelSignIn: string;
|
||||||
|
email: string;
|
||||||
|
setEmail: (newEmail: string) => void;
|
||||||
|
setPassword: (newPassword: string) => void;
|
||||||
|
error: string;
|
||||||
|
handleSubmit: (e: React.FormEvent) => void;
|
||||||
|
blockingError: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LoginForm = ({
|
||||||
|
title,
|
||||||
|
labelEmail,
|
||||||
|
labelPassword,
|
||||||
|
labelSignIn,
|
||||||
|
email,
|
||||||
|
setEmail,
|
||||||
|
setPassword,
|
||||||
|
error,
|
||||||
|
handleSubmit,
|
||||||
|
blockingError,
|
||||||
|
}: LoginFormProps) => {
|
||||||
|
return (
|
||||||
|
<Box $width="100%" $maxWidth="30rem" $margin="4rem auto" $padding="0 1rem">
|
||||||
|
<Box>
|
||||||
|
<Text
|
||||||
|
as="h1"
|
||||||
|
$textAlign="center"
|
||||||
|
$size="h3"
|
||||||
|
$theme="primary"
|
||||||
|
$variation="text"
|
||||||
|
style={{ marginBottom: '2rem' }}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
<Box>
|
||||||
|
{!!blockingError ? (
|
||||||
|
<Text
|
||||||
|
$theme="danger"
|
||||||
|
$variation="text"
|
||||||
|
$textAlign="center"
|
||||||
|
style={{ marginBottom: '1rem', display: 'block' }}
|
||||||
|
>
|
||||||
|
{blockingError === 'loading' ? '' : blockingError}
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<form onSubmit={handleSubmit} data-testId="login-form">
|
||||||
|
<Box $padding="tiny">
|
||||||
|
<InputUserEmail
|
||||||
|
setEmail={setEmail}
|
||||||
|
email={email}
|
||||||
|
label={labelEmail}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box $padding="tiny">
|
||||||
|
<InputUserPassword
|
||||||
|
label={labelPassword}
|
||||||
|
setPassword={setPassword}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<Box $padding="tiny">
|
||||||
|
<Text
|
||||||
|
$theme="danger"
|
||||||
|
$variation="text"
|
||||||
|
$textAlign="center"
|
||||||
|
style={{ marginBottom: '1rem', display: 'block' }}
|
||||||
|
>
|
||||||
|
{error}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box $padding="tiny">
|
||||||
|
<Button color="primary" type="submit" fullWidth>
|
||||||
|
{labelSignIn}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</Box>{' '}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
|
import { Box } from '@/components';
|
||||||
|
import { Footer } from '@/features/footer/Footer';
|
||||||
|
import { Header } from '@/features/header';
|
||||||
|
|
||||||
|
export function LoginLayout({ children }: PropsWithChildren) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box $height="100vh">
|
||||||
|
<Header />
|
||||||
|
<Box $css="flex: 1;" $direction="row">
|
||||||
|
{children}
|
||||||
|
</Box>
|
||||||
|
<Footer />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './LoginLayout';
|
||||||
|
export * from './LoginForm';
|
||||||
|
export * from './InputUserEmail';
|
||||||
|
export * from './InputUserPassword';
|
||||||
1
src/frontend/apps/desk/src/features/login/index.tsx
Normal file
1
src/frontend/apps/desk/src/features/login/index.tsx
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './components';
|
||||||
95
src/frontend/apps/desk/src/pages/login/index.tsx
Normal file
95
src/frontend/apps/desk/src/pages/login/index.tsx
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { ReactElement, useEffect, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { fetchAPI } from '@/api';
|
||||||
|
import { LoginForm, LoginLayout } from '@/features/login';
|
||||||
|
import { NextPageWithLayout } from '@/types/next';
|
||||||
|
|
||||||
|
const Page: NextPageWithLayout = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [email, setEmail] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
const [blockingError, setBlockingError] = useState('loading');
|
||||||
|
const { next } = router.query;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (next) {
|
||||||
|
try {
|
||||||
|
// Decode the URL-encoded next parameter
|
||||||
|
const decodedNext = decodeURIComponent(next as string);
|
||||||
|
// Extract the query string after /o/authorize/
|
||||||
|
const match = decodedNext.match(/\/o\/authorize\/\?(.*)/);
|
||||||
|
if (match) {
|
||||||
|
const params = new URLSearchParams(match[1]);
|
||||||
|
const acrValues = params.get('acr_values');
|
||||||
|
const loginHint = params.get('login_hint');
|
||||||
|
|
||||||
|
if (acrValues && acrValues !== 'eidas1') {
|
||||||
|
setBlockingError(t('This authentication level is not supported.'));
|
||||||
|
} else {
|
||||||
|
setBlockingError('');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loginHint) {
|
||||||
|
setEmail(loginHint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error parsing next parameter:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [next, t]);
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setError('');
|
||||||
|
|
||||||
|
if (blockingError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAPI('login/', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ email, password }),
|
||||||
|
credentials: 'include', // Important for session cookie
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) {
|
||||||
|
setError(t('Login failed. Please try again.'));
|
||||||
|
} else {
|
||||||
|
if (next) {
|
||||||
|
window.location.href = next as string;
|
||||||
|
} else {
|
||||||
|
window.location.href = '/authorize/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setError(t('Login failed. Please try again.'));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoginForm
|
||||||
|
title={t('Sign in')}
|
||||||
|
labelEmail={t('Email')}
|
||||||
|
labelPassword={t('Password')}
|
||||||
|
labelSignIn={t('Sign in')}
|
||||||
|
email={email}
|
||||||
|
setEmail={setEmail}
|
||||||
|
setPassword={setPassword}
|
||||||
|
error={error}
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
blockingError={blockingError}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Page.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return <LoginLayout>{page}</LoginLayout>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Page;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
type: application
|
type: application
|
||||||
name: desk
|
name: desk
|
||||||
version: 0.0.3
|
version: 0.0.4
|
||||||
|
|||||||
@@ -74,6 +74,20 @@ spec:
|
|||||||
serviceName: {{ include "desk.backend.fullname" . }}
|
serviceName: {{ include "desk.backend.fullname" . }}
|
||||||
servicePort: {{ .Values.backend.service.port }}
|
servicePort: {{ .Values.backend.service.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- path: /o
|
||||||
|
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
pathType: Prefix
|
||||||
|
{{- end }}
|
||||||
|
backend:
|
||||||
|
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
service:
|
||||||
|
name: {{ include "desk.backend.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.backend.service.port }}
|
||||||
|
{{- else }}
|
||||||
|
serviceName: {{ include "desk.backend.fullname" $ }}
|
||||||
|
servicePort: {{ $.Values.backend.service.port }}
|
||||||
|
{{- end }}
|
||||||
- path: /resource-server
|
- path: /resource-server
|
||||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
@@ -124,6 +138,20 @@ spec:
|
|||||||
serviceName: {{ include "desk.backend.fullname" $ }}
|
serviceName: {{ include "desk.backend.fullname" $ }}
|
||||||
servicePort: {{ $.Values.backend.service.port }}
|
servicePort: {{ $.Values.backend.service.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- path: /o
|
||||||
|
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
pathType: Prefix
|
||||||
|
{{- end }}
|
||||||
|
backend:
|
||||||
|
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
service:
|
||||||
|
name: {{ include "desk.backend.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.backend.service.port }}
|
||||||
|
{{- else }}
|
||||||
|
serviceName: {{ include "desk.backend.fullname" $ }}
|
||||||
|
servicePort: {{ $.Values.backend.service.port }}
|
||||||
|
{{- end }}
|
||||||
- path: /resource-server
|
- path: /resource-server
|
||||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
|
|||||||
Reference in New Issue
Block a user