UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

98 lines (97 loc) 5.7 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /* * Copyright 2025 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import Link from '@mui/material/Link'; import Snackbar from '@mui/material/Snackbar'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { generatePath, useHistory } from 'react-router-dom'; import { setToken } from '../../lib/auth'; import { getCluster, getClusterPrefixedPath } from '../../lib/cluster'; import { useClustersConf } from '../../lib/k8s'; import { testAuth } from '../../lib/k8s/apiProxy'; import { ClusterDialog } from '../cluster/Chooser'; import { DialogTitle } from '../common/Dialog'; import HeadlampLink from '../common/Link'; export default function AuthToken() { const history = useHistory(); const clusterConf = useClustersConf(); const [token, setToken] = React.useState(''); const [showError, setShowError] = React.useState(false); const clusters = useClustersConf(); const { t } = useTranslation(); function onAuthClicked() { loginWithToken(token).then(code => { // If successful, redirect. if (code === 200) { history.replace(generatePath(getClusterPrefixedPath(), { cluster: getCluster(), })); } else { setToken(''); setShowError(true); } }); } return (_jsx(PureAuthToken, { onCancel: () => history.replace('/'), title: Object.keys(clusterConf || {}).length > 1 ? t('Authentication: {{ clusterName }}', { clusterName: getCluster() }) : t('Authentication'), token: token, showError: showError, showActions: Object.keys(clusters || {}).length > 1, onChangeToken: (event) => setToken(event.target.value), onAuthClicked: onAuthClicked, onCloseError: () => { setShowError(false); } })); } export function PureAuthToken({ title, token, showActions, showError, onCancel, onAuthClicked, onChangeToken, onCloseError, }) { const { t } = useTranslation(); const cluster = getCluster(); const focusedRef = React.useCallback((node) => { if (node !== null) { // node.setAttribute('tabindex', '-1'); node.focus(); } }, []); function onClose() { // Do nothing because we're not supposed to close on backdrop click } return (_jsxs(Box, { component: "main", children: [_jsxs(ClusterDialog, { useCover: true, onClose: onClose, "aria-labelledby": "authtoken-dialog-title", children: [_jsx(DialogTitle, { id: "authtoken-dialog-title", children: title }), _jsxs(DialogContent, { children: [_jsx(DialogContentText, { children: _jsx(Trans, { t: t, children: "Please paste your authentication token." }) }), _jsx(TextField, { margin: "dense", id: "token", label: t('ID token'), type: "password", size: "small", variant: "outlined", value: token, onChange: onChangeToken, fullWidth: true, ref: focusedRef })] }), _jsxs(DialogActions, { children: [_jsx(Box, { ml: 2, children: _jsx(Typography, { variant: "body2", color: "textSecondary", children: _jsxs(Trans, { t: t, children: ["Check out how to generate a", _jsx(Link, { style: { cursor: 'pointer', marginLeft: '0.4rem' }, target: "_blank", href: "https://headlamp.dev/docs/latest/installation/#create-a-service-account-token", children: "service account token" }), "."] }) }) }), _jsx("div", { style: { flex: '1 0 0' } })] }), _jsx(Box, { overflow: "hidden", textAlign: "center", children: _jsx(HeadlampLink, { routeName: "settingsCluster", params: { clusterID: cluster || '' }, children: t('translation|Cluster settings') }) }), _jsxs(DialogActions, { children: [showActions && (_jsxs(_Fragment, { children: [_jsx(Button, { onClick: onCancel, color: "secondary", variant: "contained", children: t('translation|Cancel') }), _jsx("div", { style: { flex: '1 0 0' } })] })), _jsx(Button, { onClick: onAuthClicked, color: "primary", variant: "contained", children: t('translation|Authenticate') })] })] }), _jsx(Snackbar, { anchorOrigin: { vertical: 'bottom', horizontal: 'center', }, open: showError, autoHideDuration: 5000, onClose: onCloseError, ContentProps: { 'aria-describedby': 'message-id', }, message: _jsx("span", { id: "message-id", children: t('translation|Error authenticating') }) })] })); } async function loginWithToken(token) { try { const cluster = getCluster(); if (!cluster) { // Expectation failed. return 417; } setToken(cluster, token); await testAuth(); return 200; } catch (err) { console.error(err); return err.status; } }