import { css } from '@emotion/css'; import { useEffect, useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; import { GrafanaTheme2 } from '@grafana/data'; import { config } from '@grafana/runtime'; import { Button, ClipboardButton, DatePickerWithInput, Field, Input, Modal, RadioButtonGroup, useStyles2, } from '@grafana/ui'; const EXPIRATION_OPTIONS = [ { label: 'No expiration', value: false }, { label: 'Set expiration date', value: true }, ]; export type ServiceAccountToken = { name: string; secondsToLive?: number; }; interface Props { isOpen: boolean; token: string; serviceAccountLogin: string; onCreateToken: (token: ServiceAccountToken) => void; onClose: () => void; } export const CreateTokenModal = ({ isOpen, token, serviceAccountLogin, onCreateToken, onClose }: Props) => { const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); const maxExpirationDate = new Date(); if (config.tokenExpirationDayLimit !== undefined && config.tokenExpirationDayLimit > -1) { maxExpirationDate.setDate(maxExpirationDate.getDate() + config.tokenExpirationDayLimit + 1); } else { maxExpirationDate.setDate(8640000000000000); } const defaultExpirationDate = config.tokenExpirationDayLimit !== undefined && config.tokenExpirationDayLimit > 0; const [defaultTokenName, setDefaultTokenName] = useState(''); const [newTokenName, setNewTokenName] = useState(''); const [isWithExpirationDate, setIsWithExpirationDate] = useState(defaultExpirationDate); const [newTokenExpirationDate, setNewTokenExpirationDate] = useState(tomorrow); const [isExpirationDateValid, setIsExpirationDateValid] = useState(newTokenExpirationDate !== ''); const styles = useStyles2(getStyles); useEffect(() => { // Generate new token name every time we open modal if (isOpen) { setDefaultTokenName(`${serviceAccountLogin}-${uuidv4()}`); } }, [serviceAccountLogin, isOpen]); const onExpirationDateChange = (value: Date | string) => { const isValid = value !== ''; setIsExpirationDateValid(isValid); setNewTokenExpirationDate(value); }; const onGenerateToken = () => { onCreateToken({ name: newTokenName || defaultTokenName, secondsToLive: isWithExpirationDate ? getSecondsToLive(newTokenExpirationDate) : undefined, }); }; const onCloseInternal = () => { setNewTokenName(''); setDefaultTokenName(''); setIsWithExpirationDate(defaultExpirationDate); setNewTokenExpirationDate(tomorrow); setIsExpirationDateValid(newTokenExpirationDate !== ''); onClose(); }; const modalTitle = !token ? 'Add service account token' : 'Service account token created'; return ( {!token ? (
{ setNewTokenName(e.currentTarget.value); }} /> {isWithExpirationDate && ( )}
) : ( <>
token} > Copy clipboard
token} onClipboardCopy={onCloseInternal}> Copy to clipboard and close )}
); }; const getSecondsToLive = (date: Date | string) => { const dateAsDate = new Date(date); const now = new Date(); return Math.ceil((dateAsDate.getTime() - now.getTime()) / 1000); }; const getStyles = (theme: GrafanaTheme2) => { return { modal: css({ width: '550px', }), modalTokenRow: css({ display: 'flex', }), modalCopyToClipboardButton: css({ marginLeft: theme.spacing(0.5), }), }; };