@strapi/admin 5.13.0-beta.0 → 5.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
  2. package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
  3. package/dist/admin/admin/src/pages/Auth/components/Register.js +1 -1
  4. package/dist/admin/admin/src/pages/Auth/components/Register.js.map +1 -1
  5. package/dist/admin/admin/src/pages/Auth/components/Register.mjs +1 -1
  6. package/dist/admin/admin/src/pages/Auth/components/Register.mjs.map +1 -1
  7. package/dist/admin/admin/src/pages/Home/HomePage.js +4 -76
  8. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  9. package/dist/admin/admin/src/pages/Home/HomePage.mjs +5 -77
  10. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  11. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js +19 -1
  12. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js.map +1 -1
  13. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs +21 -3
  14. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs.map +1 -1
  15. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js +4 -1
  16. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js.map +1 -1
  17. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs +4 -1
  18. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs.map +1 -1
  19. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js +32 -2
  20. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js.map +1 -1
  21. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs +32 -2
  22. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs.map +1 -1
  23. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/EditView.js +1 -0
  24. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/EditView.js.map +1 -1
  25. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/EditView.mjs +1 -0
  26. package/dist/admin/admin/src/pages/Settings/pages/TransferTokens/EditView.mjs.map +1 -1
  27. package/dist/admin/admin/src/translations/ru.json.js +14 -1
  28. package/dist/admin/admin/src/translations/ru.json.js.map +1 -1
  29. package/dist/admin/admin/src/translations/ru.json.mjs +14 -1
  30. package/dist/admin/admin/src/translations/ru.json.mjs.map +1 -1
  31. package/dist/admin/src/pages/Settings/components/Tokens/FormHead.d.ts +4 -1
  32. package/dist/server/server/src/content-types/api-token.js +7 -0
  33. package/dist/server/server/src/content-types/api-token.js.map +1 -1
  34. package/dist/server/server/src/content-types/api-token.mjs +7 -0
  35. package/dist/server/server/src/content-types/api-token.mjs.map +1 -1
  36. package/dist/server/server/src/services/api-token.js +21 -3
  37. package/dist/server/server/src/services/api-token.js.map +1 -1
  38. package/dist/server/server/src/services/api-token.mjs +21 -3
  39. package/dist/server/server/src/services/api-token.mjs.map +1 -1
  40. package/dist/server/server/src/services/encryption.js +62 -0
  41. package/dist/server/server/src/services/encryption.js.map +1 -0
  42. package/dist/server/server/src/services/encryption.mjs +60 -0
  43. package/dist/server/server/src/services/encryption.mjs.map +1 -0
  44. package/dist/server/server/src/services/index.js +3 -1
  45. package/dist/server/server/src/services/index.js.map +1 -1
  46. package/dist/server/server/src/services/index.mjs +3 -1
  47. package/dist/server/server/src/services/index.mjs.map +1 -1
  48. package/dist/server/src/content-types/api-token.d.ts +7 -0
  49. package/dist/server/src/content-types/api-token.d.ts.map +1 -1
  50. package/dist/server/src/content-types/index.d.ts +7 -0
  51. package/dist/server/src/content-types/index.d.ts.map +1 -1
  52. package/dist/server/src/index.d.ts +11 -0
  53. package/dist/server/src/index.d.ts.map +1 -1
  54. package/dist/server/src/services/api-token.d.ts.map +1 -1
  55. package/dist/server/src/services/encryption.d.ts +6 -0
  56. package/dist/server/src/services/encryption.d.ts.map +1 -0
  57. package/dist/server/src/services/index.d.ts +4 -0
  58. package/dist/server/src/services/index.d.ts.map +1 -1
  59. package/dist/shared/contracts/api-token.d.ts +1 -0
  60. package/dist/shared/contracts/api-token.d.ts.map +1 -1
  61. package/package.json +7 -7
  62. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.js +0 -179
  63. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.js.map +0 -1
  64. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.mjs +0 -176
  65. package/dist/admin/admin/src/pages/Home/components/ContentManagerWidgets.mjs.map +0 -1
  66. package/dist/admin/admin/src/services/homepage.js +0 -28
  67. package/dist/admin/admin/src/services/homepage.js.map +0 -1
  68. package/dist/admin/admin/src/services/homepage.mjs +0 -26
  69. package/dist/admin/admin/src/services/homepage.mjs.map +0 -1
  70. package/dist/admin/src/pages/Home/components/ContentManagerWidgets.d.ts +0 -3
  71. package/dist/admin/src/services/homepage.d.ts +0 -5
@@ -1 +1 @@
1
- {"version":3,"file":"EditView.mjs","sources":["../../../../../../../../admin/src/pages/Settings/pages/TransferTokens/EditView.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Flex, Grid, Typography } from '@strapi/design-system';\nimport { Formik, Form, FormikErrors, FormikHelpers } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useLocation, useNavigate, useMatch } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { useGuidedTour } from '../../../../components/GuidedTour/Provider';\nimport { Layouts } from '../../../../components/Layouts/Layout';\nimport { Page } from '../../../../components/PageHelpers';\nimport { useTypedSelector } from '../../../../core/store/hooks';\nimport { useNotification } from '../../../../features/Notifications';\nimport { useTracking } from '../../../../features/Tracking';\nimport { useAPIErrorHandler } from '../../../../hooks/useAPIErrorHandler';\nimport { useRBAC } from '../../../../hooks/useRBAC';\nimport {\n useCreateTransferTokenMutation,\n useGetTransferTokenQuery,\n useUpdateTransferTokenMutation,\n} from '../../../../services/transferTokens';\nimport { isBaseQueryError } from '../../../../utils/baseQuery';\nimport { translatedErrors } from '../../../../utils/translatedErrors';\nimport { TRANSFER_TOKEN_TYPE } from '../../components/Tokens/constants';\nimport { FormHead } from '../../components/Tokens/FormHead';\nimport { LifeSpanInput } from '../../components/Tokens/LifeSpanInput';\nimport { TokenBox } from '../../components/Tokens/TokenBox';\nimport { TokenDescription } from '../../components/Tokens/TokenDescription';\nimport { TokenName } from '../../components/Tokens/TokenName';\nimport { TokenTypeSelect } from '../../components/Tokens/TokenTypeSelect';\n\nimport type {\n TransferToken,\n SanitizedTransferToken,\n} from '../../../../../../shared/contracts/transfer';\n\nconst schema = yup.object().shape({\n name: yup.string().max(100).required(translatedErrors.required.id),\n description: yup.string().nullable(),\n lifespan: yup.number().integer().min(0).nullable().defined(translatedErrors.required.id),\n permissions: yup.string().required(translatedErrors.required.id),\n});\n\n/* -------------------------------------------------------------------------------------------------\n * EditView\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditView = () => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const navigate = useNavigate();\n const { state: locationState } = useLocation();\n const [transferToken, setTransferToken] = React.useState<\n TransferToken | SanitizedTransferToken | null\n >(\n locationState && 'accessKey' in locationState.transferToken\n ? {\n ...locationState.transferToken,\n }\n : null\n );\n const { trackUsage } = useTracking();\n const setCurrentStep = useGuidedTour('EditView', (state) => state.setCurrentStep);\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.settings?.['transfer-tokens']\n );\n const {\n allowedActions: { canCreate, canUpdate, canRegenerate },\n } = useRBAC(permissions);\n const match = useMatch('/settings/transfer-tokens/:id');\n\n const id = match?.params?.id;\n const isCreating = id === 'create';\n\n const {\n _unstableFormatAPIError: formatAPIError,\n _unstableFormatValidationErrors: formatValidationErrors,\n } = useAPIErrorHandler();\n\n React.useEffect(() => {\n trackUsage(isCreating ? 'didAddTokenFromList' : 'didEditTokenFromList', {\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n }, [isCreating, trackUsage]);\n\n const { data, error } = useGetTransferTokenQuery(id!, {\n skip: isCreating || transferToken !== null || !id,\n });\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(error),\n });\n }\n }, [error, formatAPIError, toggleNotification]);\n\n React.useEffect(() => {\n if (data) {\n setTransferToken(data);\n }\n }, [data]);\n\n const [createToken] = useCreateTransferTokenMutation();\n const [updateToken] = useUpdateTransferTokenMutation();\n\n const handleSubmit = async (body: FormValues, formik: FormikHelpers<FormValues>) => {\n trackUsage(isCreating ? 'willCreateToken' : 'willEditToken', {\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n\n const permissions = body.permissions.split('-');\n\n const isPermissionsTransferPermission = (\n permission: string[]\n ): permission is Array<'push' | 'pull'> => {\n if (permission.length === 1) {\n return permission[0] === 'push' || permission[0] === 'pull';\n }\n\n return permission[0] === 'push' && permission[1] === 'pull';\n };\n\n // this type-guard is necessary to satisfy the type for `permissions` in the request body,\n // because String.split returns stringp[]\n if (isPermissionsTransferPermission(permissions)) {\n try {\n if (isCreating) {\n const res = await createToken({\n ...body,\n // lifespan must be \"null\" for unlimited (0 would mean instantly expired and isn't accepted)\n lifespan:\n body?.lifespan && body.lifespan !== '0'\n ? parseInt(body.lifespan.toString(), 10)\n : null,\n permissions,\n });\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n formik.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(res.error),\n });\n }\n\n return;\n }\n\n setTransferToken(res.data);\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'notification.success.transfertokencreated',\n defaultMessage: 'Transfer Token successfully created',\n }),\n });\n\n trackUsage('didCreateToken', {\n type: transferToken?.permissions,\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n\n navigate(`../transfer-tokens/${res.data.id.toString()}`, {\n replace: true,\n state: { transferToken: res.data },\n });\n } else {\n const res = await updateToken({\n id: id!,\n name: body.name,\n description: body.description,\n permissions,\n });\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n formik.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(res.error),\n });\n }\n\n return;\n }\n\n setTransferToken(res.data);\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'notification.success.transfertokenedited',\n defaultMessage: 'Transfer Token successfully edited',\n }),\n });\n\n trackUsage('didEditToken', {\n type: transferToken?.permissions,\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n }\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'Something went wrong',\n }),\n });\n }\n }\n };\n\n const canEditInputs = (canUpdate && !isCreating) || (canCreate && isCreating);\n const isLoading = !isCreating && !transferToken;\n\n if (isLoading) {\n return <Page.Loading />;\n }\n\n return (\n <Page.Main>\n <Page.Title>\n {formatMessage(\n { id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },\n {\n name: 'Transfer Tokens',\n }\n )}\n </Page.Title>\n <Formik\n validationSchema={schema}\n validateOnChange={false}\n initialValues={\n {\n name: transferToken?.name || '',\n description: transferToken?.description || '',\n lifespan: transferToken?.lifespan || null,\n /**\n * We need to cast the permissions to satisfy the type for `permissions`\n * in the request body incase we don't have a transferToken and instead\n * use an empty string.\n */\n permissions: (transferToken?.permissions.join('-') ?? '') as FormValues['permissions'],\n } satisfies FormValues\n }\n enableReinitialize\n onSubmit={(body, actions) => handleSubmit(body, actions)}\n >\n {({ errors, handleChange, isSubmitting, values }) => {\n return (\n <Form>\n <FormHead\n title={{\n id: 'Settings.transferTokens.createPage.title',\n defaultMessage: 'TokenCreate Transfer Token',\n }}\n token={transferToken}\n setToken={setTransferToken}\n canEditInputs={canEditInputs}\n canRegenerate={canRegenerate}\n isSubmitting={isSubmitting}\n regenerateUrl=\"/admin/transfer/tokens/\"\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {transferToken &&\n Boolean(transferToken?.name) &&\n 'accessKey' in transferToken && (\n <TokenBox token={transferToken.accessKey} tokenType={TRANSFER_TOKEN_TYPE} />\n )}\n <FormTransferTokenContainer\n errors={errors}\n onChange={handleChange}\n canEditInputs={canEditInputs}\n isCreating={isCreating}\n values={values}\n transferToken={transferToken}\n />\n </Flex>\n </Layouts.Content>\n </Form>\n );\n }}\n </Formik>\n </Page.Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ProtectedEditView\n * -----------------------------------------------------------------------------------------------*/\n\nconst ProtectedEditView = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.settings?.['transfer-tokens'].read\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <EditView />\n </Page.Protect>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * FormTransferTokenContainer\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FormValues extends Pick<TransferToken, 'description' | 'name' | 'lifespan'> {\n permissions: Extract<TransferToken['permissions'][number], string>;\n}\n\ninterface FormTransferTokenContainerProps {\n errors: FormikErrors<FormValues>;\n onChange: ({ target: { name, value } }: { target: { name: string; value: string } }) => void;\n canEditInputs: boolean;\n values: FormValues;\n isCreating: boolean;\n transferToken: Partial<TransferToken> | null;\n}\n\nconst FormTransferTokenContainer = ({\n errors = {},\n onChange,\n canEditInputs,\n isCreating,\n values,\n transferToken = {},\n}: FormTransferTokenContainerProps) => {\n const { formatMessage } = useIntl();\n\n const typeOptions = [\n {\n value: 'push',\n label: {\n id: 'Settings.transferTokens.types.push',\n defaultMessage: 'Push',\n },\n },\n {\n value: 'pull',\n label: {\n id: 'Settings.transferTokens.types.pull',\n defaultMessage: 'Pull',\n },\n },\n {\n value: 'push-pull',\n label: {\n id: 'Settings.transferTokens.types.push-pull',\n defaultMessage: 'Full Access',\n },\n },\n ];\n\n return (\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"filterShadow\"\n paddingTop={6}\n paddingBottom={6}\n paddingLeft={7}\n paddingRight={7}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={4}>\n <Typography variant=\"delta\" tag=\"h2\">\n {formatMessage({\n id: 'global.details',\n defaultMessage: 'Details',\n })}\n </Typography>\n <Grid.Root gap={5}>\n <Grid.Item key=\"name\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <TokenName\n error={errors['name']}\n value={values['name']}\n canEditInputs={canEditInputs}\n onChange={onChange}\n />\n </Grid.Item>\n <Grid.Item key=\"description\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <TokenDescription\n error={errors['description']}\n value={values['description']}\n canEditInputs={canEditInputs}\n onChange={onChange}\n />\n </Grid.Item>\n <Grid.Item key=\"lifespan\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <LifeSpanInput\n isCreating={isCreating}\n error={errors['lifespan']}\n value={values['lifespan']}\n onChange={onChange}\n token={transferToken}\n />\n </Grid.Item>\n <Grid.Item key=\"permissions\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <TokenTypeSelect\n name=\"permissions\"\n value={values['permissions']}\n error={errors['permissions']}\n label={{\n id: 'Settings.tokens.form.type',\n defaultMessage: 'Token type',\n }}\n // @ts-expect-error – DS Select passes number | string, will be fixed in V2\n onChange={(value: string) => {\n onChange({ target: { name: 'permissions', value } });\n }}\n options={typeOptions}\n canEditInputs={canEditInputs}\n />\n </Grid.Item>\n </Grid.Root>\n </Flex>\n </Box>\n );\n};\n\nexport { EditView, ProtectedEditView };\n"],"names":["schema","yup","object","shape","name","string","max","required","translatedErrors","id","description","nullable","lifespan","number","integer","min","defined","permissions","EditView","formatMessage","useIntl","toggleNotification","useNotification","navigate","useNavigate","state","locationState","useLocation","transferToken","setTransferToken","React","useState","trackUsage","useTracking","useGuidedTour","setCurrentStep","useTypedSelector","admin_app","settings","allowedActions","canCreate","canUpdate","canRegenerate","useRBAC","match","useMatch","params","isCreating","_unstableFormatAPIError","formatAPIError","_unstableFormatValidationErrors","formatValidationErrors","useAPIErrorHandler","useEffect","tokenType","TRANSFER_TOKEN_TYPE","data","error","useGetTransferTokenQuery","skip","type","message","createToken","useCreateTransferTokenMutation","updateToken","useUpdateTransferTokenMutation","handleSubmit","body","formik","split","isPermissionsTransferPermission","permission","length","res","parseInt","toString","isBaseQueryError","setErrors","defaultMessage","replace","err","canEditInputs","isLoading","_jsx","Page","Loading","_jsxs","Main","Title","Formik","validationSchema","validateOnChange","initialValues","join","enableReinitialize","onSubmit","actions","errors","handleChange","isSubmitting","values","Form","FormHead","title","token","setToken","regenerateUrl","Layouts","Content","Flex","direction","alignItems","gap","Boolean","TokenBox","accessKey","FormTransferTokenContainer","onChange","ProtectedEditView","read","Protect","typeOptions","value","label","Box","background","hasRadius","shadow","paddingTop","paddingBottom","paddingLeft","paddingRight","Typography","variant","tag","Grid","Root","Item","col","xs","TokenName","TokenDescription","LifeSpanInput","TokenTypeSelect","target","options"],"mappings":"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"}
1
+ {"version":3,"file":"EditView.mjs","sources":["../../../../../../../../admin/src/pages/Settings/pages/TransferTokens/EditView.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Flex, Grid, Typography } from '@strapi/design-system';\nimport { Formik, Form, FormikErrors, FormikHelpers } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useLocation, useNavigate, useMatch } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { useGuidedTour } from '../../../../components/GuidedTour/Provider';\nimport { Layouts } from '../../../../components/Layouts/Layout';\nimport { Page } from '../../../../components/PageHelpers';\nimport { useTypedSelector } from '../../../../core/store/hooks';\nimport { useNotification } from '../../../../features/Notifications';\nimport { useTracking } from '../../../../features/Tracking';\nimport { useAPIErrorHandler } from '../../../../hooks/useAPIErrorHandler';\nimport { useRBAC } from '../../../../hooks/useRBAC';\nimport {\n useCreateTransferTokenMutation,\n useGetTransferTokenQuery,\n useUpdateTransferTokenMutation,\n} from '../../../../services/transferTokens';\nimport { isBaseQueryError } from '../../../../utils/baseQuery';\nimport { translatedErrors } from '../../../../utils/translatedErrors';\nimport { TRANSFER_TOKEN_TYPE } from '../../components/Tokens/constants';\nimport { FormHead } from '../../components/Tokens/FormHead';\nimport { LifeSpanInput } from '../../components/Tokens/LifeSpanInput';\nimport { TokenBox } from '../../components/Tokens/TokenBox';\nimport { TokenDescription } from '../../components/Tokens/TokenDescription';\nimport { TokenName } from '../../components/Tokens/TokenName';\nimport { TokenTypeSelect } from '../../components/Tokens/TokenTypeSelect';\n\nimport type {\n TransferToken,\n SanitizedTransferToken,\n} from '../../../../../../shared/contracts/transfer';\n\nconst schema = yup.object().shape({\n name: yup.string().max(100).required(translatedErrors.required.id),\n description: yup.string().nullable(),\n lifespan: yup.number().integer().min(0).nullable().defined(translatedErrors.required.id),\n permissions: yup.string().required(translatedErrors.required.id),\n});\n\n/* -------------------------------------------------------------------------------------------------\n * EditView\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditView = () => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const navigate = useNavigate();\n const { state: locationState } = useLocation();\n const [transferToken, setTransferToken] = React.useState<\n TransferToken | SanitizedTransferToken | null\n >(\n locationState && 'accessKey' in locationState.transferToken\n ? {\n ...locationState.transferToken,\n }\n : null\n );\n const { trackUsage } = useTracking();\n const setCurrentStep = useGuidedTour('EditView', (state) => state.setCurrentStep);\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.settings?.['transfer-tokens']\n );\n const {\n allowedActions: { canCreate, canUpdate, canRegenerate },\n } = useRBAC(permissions);\n const match = useMatch('/settings/transfer-tokens/:id');\n\n const id = match?.params?.id;\n const isCreating = id === 'create';\n\n const {\n _unstableFormatAPIError: formatAPIError,\n _unstableFormatValidationErrors: formatValidationErrors,\n } = useAPIErrorHandler();\n\n React.useEffect(() => {\n trackUsage(isCreating ? 'didAddTokenFromList' : 'didEditTokenFromList', {\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n }, [isCreating, trackUsage]);\n\n const { data, error } = useGetTransferTokenQuery(id!, {\n skip: isCreating || transferToken !== null || !id,\n });\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(error),\n });\n }\n }, [error, formatAPIError, toggleNotification]);\n\n React.useEffect(() => {\n if (data) {\n setTransferToken(data);\n }\n }, [data]);\n\n const [createToken] = useCreateTransferTokenMutation();\n const [updateToken] = useUpdateTransferTokenMutation();\n\n const handleSubmit = async (body: FormValues, formik: FormikHelpers<FormValues>) => {\n trackUsage(isCreating ? 'willCreateToken' : 'willEditToken', {\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n\n const permissions = body.permissions.split('-');\n\n const isPermissionsTransferPermission = (\n permission: string[]\n ): permission is Array<'push' | 'pull'> => {\n if (permission.length === 1) {\n return permission[0] === 'push' || permission[0] === 'pull';\n }\n\n return permission[0] === 'push' && permission[1] === 'pull';\n };\n\n // this type-guard is necessary to satisfy the type for `permissions` in the request body,\n // because String.split returns stringp[]\n if (isPermissionsTransferPermission(permissions)) {\n try {\n if (isCreating) {\n const res = await createToken({\n ...body,\n // lifespan must be \"null\" for unlimited (0 would mean instantly expired and isn't accepted)\n lifespan:\n body?.lifespan && body.lifespan !== '0'\n ? parseInt(body.lifespan.toString(), 10)\n : null,\n permissions,\n });\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n formik.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(res.error),\n });\n }\n\n return;\n }\n\n setTransferToken(res.data);\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'notification.success.transfertokencreated',\n defaultMessage: 'Transfer Token successfully created',\n }),\n });\n\n trackUsage('didCreateToken', {\n type: transferToken?.permissions,\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n\n navigate(`../transfer-tokens/${res.data.id.toString()}`, {\n replace: true,\n state: { transferToken: res.data },\n });\n } else {\n const res = await updateToken({\n id: id!,\n name: body.name,\n description: body.description,\n permissions,\n });\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n formik.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(res.error),\n });\n }\n\n return;\n }\n\n setTransferToken(res.data);\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'notification.success.transfertokenedited',\n defaultMessage: 'Transfer Token successfully edited',\n }),\n });\n\n trackUsage('didEditToken', {\n type: transferToken?.permissions,\n tokenType: TRANSFER_TOKEN_TYPE,\n });\n }\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'Something went wrong',\n }),\n });\n }\n }\n };\n\n const canEditInputs = (canUpdate && !isCreating) || (canCreate && isCreating);\n const isLoading = !isCreating && !transferToken;\n\n if (isLoading) {\n return <Page.Loading />;\n }\n\n return (\n <Page.Main>\n <Page.Title>\n {formatMessage(\n { id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },\n {\n name: 'Transfer Tokens',\n }\n )}\n </Page.Title>\n <Formik\n validationSchema={schema}\n validateOnChange={false}\n initialValues={\n {\n name: transferToken?.name || '',\n description: transferToken?.description || '',\n lifespan: transferToken?.lifespan || null,\n /**\n * We need to cast the permissions to satisfy the type for `permissions`\n * in the request body incase we don't have a transferToken and instead\n * use an empty string.\n */\n permissions: (transferToken?.permissions.join('-') ?? '') as FormValues['permissions'],\n } satisfies FormValues\n }\n enableReinitialize\n onSubmit={(body, actions) => handleSubmit(body, actions)}\n >\n {({ errors, handleChange, isSubmitting, values }) => {\n return (\n <Form>\n <FormHead\n title={{\n id: 'Settings.transferTokens.createPage.title',\n defaultMessage: 'TokenCreate Transfer Token',\n }}\n token={transferToken}\n setToken={setTransferToken}\n canShowToken={false}\n canEditInputs={canEditInputs}\n canRegenerate={canRegenerate}\n isSubmitting={isSubmitting}\n regenerateUrl=\"/admin/transfer/tokens/\"\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {transferToken &&\n Boolean(transferToken?.name) &&\n 'accessKey' in transferToken && (\n <TokenBox token={transferToken.accessKey} tokenType={TRANSFER_TOKEN_TYPE} />\n )}\n <FormTransferTokenContainer\n errors={errors}\n onChange={handleChange}\n canEditInputs={canEditInputs}\n isCreating={isCreating}\n values={values}\n transferToken={transferToken}\n />\n </Flex>\n </Layouts.Content>\n </Form>\n );\n }}\n </Formik>\n </Page.Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ProtectedEditView\n * -----------------------------------------------------------------------------------------------*/\n\nconst ProtectedEditView = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.settings?.['transfer-tokens'].read\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <EditView />\n </Page.Protect>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * FormTransferTokenContainer\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FormValues extends Pick<TransferToken, 'description' | 'name' | 'lifespan'> {\n permissions: Extract<TransferToken['permissions'][number], string>;\n}\n\ninterface FormTransferTokenContainerProps {\n errors: FormikErrors<FormValues>;\n onChange: ({ target: { name, value } }: { target: { name: string; value: string } }) => void;\n canEditInputs: boolean;\n values: FormValues;\n isCreating: boolean;\n transferToken: Partial<TransferToken> | null;\n}\n\nconst FormTransferTokenContainer = ({\n errors = {},\n onChange,\n canEditInputs,\n isCreating,\n values,\n transferToken = {},\n}: FormTransferTokenContainerProps) => {\n const { formatMessage } = useIntl();\n\n const typeOptions = [\n {\n value: 'push',\n label: {\n id: 'Settings.transferTokens.types.push',\n defaultMessage: 'Push',\n },\n },\n {\n value: 'pull',\n label: {\n id: 'Settings.transferTokens.types.pull',\n defaultMessage: 'Pull',\n },\n },\n {\n value: 'push-pull',\n label: {\n id: 'Settings.transferTokens.types.push-pull',\n defaultMessage: 'Full Access',\n },\n },\n ];\n\n return (\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"filterShadow\"\n paddingTop={6}\n paddingBottom={6}\n paddingLeft={7}\n paddingRight={7}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={4}>\n <Typography variant=\"delta\" tag=\"h2\">\n {formatMessage({\n id: 'global.details',\n defaultMessage: 'Details',\n })}\n </Typography>\n <Grid.Root gap={5}>\n <Grid.Item key=\"name\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <TokenName\n error={errors['name']}\n value={values['name']}\n canEditInputs={canEditInputs}\n onChange={onChange}\n />\n </Grid.Item>\n <Grid.Item key=\"description\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <TokenDescription\n error={errors['description']}\n value={values['description']}\n canEditInputs={canEditInputs}\n onChange={onChange}\n />\n </Grid.Item>\n <Grid.Item key=\"lifespan\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <LifeSpanInput\n isCreating={isCreating}\n error={errors['lifespan']}\n value={values['lifespan']}\n onChange={onChange}\n token={transferToken}\n />\n </Grid.Item>\n <Grid.Item key=\"permissions\" col={6} xs={12} direction=\"column\" alignItems=\"stretch\">\n <TokenTypeSelect\n name=\"permissions\"\n value={values['permissions']}\n error={errors['permissions']}\n label={{\n id: 'Settings.tokens.form.type',\n defaultMessage: 'Token type',\n }}\n // @ts-expect-error – DS Select passes number | string, will be fixed in V2\n onChange={(value: string) => {\n onChange({ target: { name: 'permissions', value } });\n }}\n options={typeOptions}\n canEditInputs={canEditInputs}\n />\n </Grid.Item>\n </Grid.Root>\n </Flex>\n </Box>\n );\n};\n\nexport { EditView, ProtectedEditView };\n"],"names":["schema","yup","object","shape","name","string","max","required","translatedErrors","id","description","nullable","lifespan","number","integer","min","defined","permissions","EditView","formatMessage","useIntl","toggleNotification","useNotification","navigate","useNavigate","state","locationState","useLocation","transferToken","setTransferToken","React","useState","trackUsage","useTracking","useGuidedTour","setCurrentStep","useTypedSelector","admin_app","settings","allowedActions","canCreate","canUpdate","canRegenerate","useRBAC","match","useMatch","params","isCreating","_unstableFormatAPIError","formatAPIError","_unstableFormatValidationErrors","formatValidationErrors","useAPIErrorHandler","useEffect","tokenType","TRANSFER_TOKEN_TYPE","data","error","useGetTransferTokenQuery","skip","type","message","createToken","useCreateTransferTokenMutation","updateToken","useUpdateTransferTokenMutation","handleSubmit","body","formik","split","isPermissionsTransferPermission","permission","length","res","parseInt","toString","isBaseQueryError","setErrors","defaultMessage","replace","err","canEditInputs","isLoading","_jsx","Page","Loading","_jsxs","Main","Title","Formik","validationSchema","validateOnChange","initialValues","join","enableReinitialize","onSubmit","actions","errors","handleChange","isSubmitting","values","Form","FormHead","title","token","setToken","canShowToken","regenerateUrl","Layouts","Content","Flex","direction","alignItems","gap","Boolean","TokenBox","accessKey","FormTransferTokenContainer","onChange","ProtectedEditView","read","Protect","typeOptions","value","label","Box","background","hasRadius","shadow","paddingTop","paddingBottom","paddingLeft","paddingRight","Typography","variant","tag","Grid","Root","Item","col","xs","TokenName","TokenDescription","LifeSpanInput","TokenTypeSelect","target","options"],"mappings":"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"}
@@ -451,6 +451,13 @@ var ru = {
451
451
  "app.components.HomePage.button.blog": "Смотрите больше в нашем блоге",
452
452
  "app.components.HomePage.community": "Присоединиться к нашему сообществу",
453
453
  "app.components.HomePage.community.content": "Участвуйте в обсуждениях с членами команды и разработчиками.",
454
+ "app.components.HomePage.community.links.github": "GitHub",
455
+ "app.components.HomePage.community.links.discord": "Discord",
456
+ "app.components.HomePage.community.links.reddit": "Reddit",
457
+ "app.components.HomePage.community.links.twitter": "X",
458
+ "app.components.HomePage.community.links.forum": "Форум",
459
+ "app.components.HomePage.community.links.blog": "Блог",
460
+ "app.components.HomePage.community.links.career": "Мы принимаем на работу!",
454
461
  "app.components.HomePage.create": "Создайте свой первый тип контента",
455
462
  "app.components.HomePage.roadmap": "Ознакомьтесь с нашей дорожной картой",
456
463
  "app.components.HomePage.welcome": "Добро пожаловать на борт 👋",
@@ -504,7 +511,8 @@ var ru = {
504
511
  "app.components.NpsSurvey.no-recommendation": "Совсем маловероятно",
505
512
  "app.components.NpsSurvey.submit-feedback": "Отправить отзыв",
506
513
  "app.components.Official": "Официальный",
507
- "app.components.Onboarding.help.button": "Кнопка помощь",
514
+ "app.components.Onboarding.help.button": "Открыть меню помощи",
515
+ "app.components.Onboarding.help.button-close": "Закрыть меню помощи",
508
516
  "app.components.Onboarding.label.completed": "% завершено",
509
517
  "app.components.Onboarding.link.build-content": "Создайте архитектуру контента",
510
518
  "app.components.Onboarding.link.manage-content": "Добавляйте и управляйте контентом",
@@ -548,6 +556,9 @@ var ru = {
548
556
  "app.containers.Users.EditPage.header.label-loading": "Редактировать пользователя",
549
557
  "app.containers.Users.EditPage.roles-bloc-title": "Атрибуты ролей",
550
558
  "app.containers.Users.ModalForm.footer.button-success": "Создать пользователя",
559
+ "app.error": "Что-то пошло не так",
560
+ "app.error.message": "Похоже, что в вашем экземпляре обнаружена ошибка, но мы с вами справимся. Пожалуйста, сообщите об этом своей технической команде, чтобы они могли выяснить источник проблемы и сообщить нам о проблеме, открыв отчет об ошибке по ссылке: {link}.",
561
+ "app.error.copy": "Скопировать в буфер обмена",
551
562
  "app.links.configure-view": "Настройка представления",
552
563
  "app.page.not.found": "Упс! Мы не можем найти страницу, которую вы ищете...",
553
564
  "app.static.links.cheatsheet": "Шпаргалка",
@@ -661,6 +672,7 @@ var ru = {
661
672
  "components.popUpWarning.button.confirm": "Да, подтвердить",
662
673
  "components.popUpWarning.message": "Вы уверены, что хотите удалить это?",
663
674
  "components.popUpWarning.title": "Пожалуйста, подтвердите",
675
+ "containers.list.displayedFields": "Отображаемые поля",
664
676
  dark: dark,
665
677
  "form.button.continue": "Продолжить",
666
678
  "form.button.done": "Выполнено",
@@ -681,6 +693,7 @@ var ru = {
681
693
  "global.enabled": "Включено",
682
694
  "global.finish": "Готово",
683
695
  "global.fullname": "{firstname} {lastname}",
696
+ "global.localeToggle.label": "Выбор языка интерфейса",
684
697
  "global.marketplace": "Маркет",
685
698
  "global.name": "Имя",
686
699
  "global.none": "Нет",
@@ -1 +1 @@
1
- {"version":3,"file":"ru.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ru.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -447,6 +447,13 @@ var ru = {
447
447
  "app.components.HomePage.button.blog": "Смотрите больше в нашем блоге",
448
448
  "app.components.HomePage.community": "Присоединиться к нашему сообществу",
449
449
  "app.components.HomePage.community.content": "Участвуйте в обсуждениях с членами команды и разработчиками.",
450
+ "app.components.HomePage.community.links.github": "GitHub",
451
+ "app.components.HomePage.community.links.discord": "Discord",
452
+ "app.components.HomePage.community.links.reddit": "Reddit",
453
+ "app.components.HomePage.community.links.twitter": "X",
454
+ "app.components.HomePage.community.links.forum": "Форум",
455
+ "app.components.HomePage.community.links.blog": "Блог",
456
+ "app.components.HomePage.community.links.career": "Мы принимаем на работу!",
450
457
  "app.components.HomePage.create": "Создайте свой первый тип контента",
451
458
  "app.components.HomePage.roadmap": "Ознакомьтесь с нашей дорожной картой",
452
459
  "app.components.HomePage.welcome": "Добро пожаловать на борт 👋",
@@ -500,7 +507,8 @@ var ru = {
500
507
  "app.components.NpsSurvey.no-recommendation": "Совсем маловероятно",
501
508
  "app.components.NpsSurvey.submit-feedback": "Отправить отзыв",
502
509
  "app.components.Official": "Официальный",
503
- "app.components.Onboarding.help.button": "Кнопка помощь",
510
+ "app.components.Onboarding.help.button": "Открыть меню помощи",
511
+ "app.components.Onboarding.help.button-close": "Закрыть меню помощи",
504
512
  "app.components.Onboarding.label.completed": "% завершено",
505
513
  "app.components.Onboarding.link.build-content": "Создайте архитектуру контента",
506
514
  "app.components.Onboarding.link.manage-content": "Добавляйте и управляйте контентом",
@@ -544,6 +552,9 @@ var ru = {
544
552
  "app.containers.Users.EditPage.header.label-loading": "Редактировать пользователя",
545
553
  "app.containers.Users.EditPage.roles-bloc-title": "Атрибуты ролей",
546
554
  "app.containers.Users.ModalForm.footer.button-success": "Создать пользователя",
555
+ "app.error": "Что-то пошло не так",
556
+ "app.error.message": "Похоже, что в вашем экземпляре обнаружена ошибка, но мы с вами справимся. Пожалуйста, сообщите об этом своей технической команде, чтобы они могли выяснить источник проблемы и сообщить нам о проблеме, открыв отчет об ошибке по ссылке: {link}.",
557
+ "app.error.copy": "Скопировать в буфер обмена",
547
558
  "app.links.configure-view": "Настройка представления",
548
559
  "app.page.not.found": "Упс! Мы не можем найти страницу, которую вы ищете...",
549
560
  "app.static.links.cheatsheet": "Шпаргалка",
@@ -657,6 +668,7 @@ var ru = {
657
668
  "components.popUpWarning.button.confirm": "Да, подтвердить",
658
669
  "components.popUpWarning.message": "Вы уверены, что хотите удалить это?",
659
670
  "components.popUpWarning.title": "Пожалуйста, подтвердите",
671
+ "containers.list.displayedFields": "Отображаемые поля",
660
672
  dark: dark,
661
673
  "form.button.continue": "Продолжить",
662
674
  "form.button.done": "Выполнено",
@@ -677,6 +689,7 @@ var ru = {
677
689
  "global.enabled": "Включено",
678
690
  "global.finish": "Готово",
679
691
  "global.fullname": "{firstname} {lastname}",
692
+ "global.localeToggle.label": "Выбор языка интерфейса",
680
693
  "global.marketplace": "Маркет",
681
694
  "global.name": "Имя",
682
695
  "global.none": "Нет",
@@ -1 +1 @@
1
- {"version":3,"file":"ru.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ru.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -9,9 +9,12 @@ interface FormHeadProps<TToken extends Token | null> {
9
9
  token: TToken;
10
10
  canEditInputs: boolean;
11
11
  canRegenerate: boolean;
12
+ canShowToken?: boolean;
12
13
  setToken: (token: TToken) => void;
14
+ toggleToken?: () => void;
15
+ showToken?: boolean;
13
16
  isSubmitting: boolean;
14
17
  regenerateUrl: string;
15
18
  }
16
- export declare const FormHead: <TToken extends Token | null>({ title, token, setToken, canEditInputs, canRegenerate, isSubmitting, regenerateUrl, }: FormHeadProps<TToken>) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const FormHead: <TToken extends Token | null>({ title, token, setToken, toggleToken, showToken, canShowToken, canEditInputs, canRegenerate, isSubmitting, regenerateUrl, }: FormHeadProps<TToken>) => import("react/jsx-runtime").JSX.Element;
17
20
  export {};
@@ -49,6 +49,13 @@ var apiToken = {
49
49
  required: true,
50
50
  searchable: false
51
51
  },
52
+ encryptedKey: {
53
+ type: 'text',
54
+ minLength: 1,
55
+ configurable: false,
56
+ required: false,
57
+ searchable: false
58
+ },
52
59
  lastUsedAt: {
53
60
  type: 'datetime',
54
61
  configurable: false,
@@ -1 +1 @@
1
- {"version":3,"file":"api-token.js","sources":["../../../../../server/src/content-types/api-token.ts"],"sourcesContent":["import constants from '../services/constants';\n\nexport default {\n collectionName: 'strapi_api_tokens',\n info: {\n name: 'Api Token',\n singularName: 'api-token',\n pluralName: 'api-tokens',\n displayName: 'Api Token',\n description: '',\n },\n options: {},\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n name: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n unique: true,\n },\n description: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: false,\n default: '',\n },\n type: {\n type: 'enumeration',\n enum: Object.values(constants.API_TOKEN_TYPE),\n configurable: false,\n required: true,\n default: constants.API_TOKEN_TYPE.READ_ONLY,\n },\n accessKey: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n searchable: false,\n },\n lastUsedAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n permissions: {\n type: 'relation',\n target: 'admin::api-token-permission',\n relation: 'oneToMany',\n mappedBy: 'token',\n configurable: false,\n required: false,\n },\n expiresAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n lifespan: {\n type: 'biginteger',\n configurable: false,\n required: false,\n },\n },\n};\n"],"names":["collectionName","info","name","singularName","pluralName","displayName","description","options","pluginOptions","visible","attributes","type","minLength","configurable","required","unique","default","enum","Object","values","constants","API_TOKEN_TYPE","READ_ONLY","accessKey","searchable","lastUsedAt","permissions","target","relation","mappedBy","expiresAt","lifespan"],"mappings":";;;;AAEA,eAAe;IACbA,cAAgB,EAAA,mBAAA;IAChBC,IAAM,EAAA;QACJC,IAAM,EAAA,WAAA;QACNC,YAAc,EAAA,WAAA;QACdC,UAAY,EAAA,YAAA;QACZC,WAAa,EAAA,WAAA;QACbC,WAAa,EAAA;AACf,KAAA;AACAC,IAAAA,OAAAA,EAAS,EAAC;IACVC,aAAe,EAAA;QACb,iBAAmB,EAAA;YACjBC,OAAS,EAAA;AACX,SAAA;QACA,sBAAwB,EAAA;YACtBA,OAAS,EAAA;AACX;AACF,KAAA;IACAC,UAAY,EAAA;QACVR,IAAM,EAAA;YACJS,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVC,MAAQ,EAAA;AACV,SAAA;QACAT,WAAa,EAAA;YACXK,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,KAAA;YACVE,OAAS,EAAA;AACX,SAAA;QACAL,IAAM,EAAA;YACJA,IAAM,EAAA,aAAA;AACNM,YAAAA,IAAAA,EAAMC,MAAOC,CAAAA,MAAM,CAACC,SAAAA,CAAUC,cAAc,CAAA;YAC5CR,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVE,OAASI,EAAAA,SAAAA,CAAUC,cAAc,CAACC;AACpC,SAAA;QACAC,SAAW,EAAA;YACTZ,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVU,UAAY,EAAA;AACd,SAAA;QACAC,UAAY,EAAA;YACVd,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAY,WAAa,EAAA;YACXf,IAAM,EAAA,UAAA;YACNgB,MAAQ,EAAA,6BAAA;YACRC,QAAU,EAAA,WAAA;YACVC,QAAU,EAAA,OAAA;YACVhB,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAgB,SAAW,EAAA;YACTnB,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAiB,QAAU,EAAA;YACRpB,IAAM,EAAA,YAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ;AACF;AACF,CAAE;;;;"}
1
+ {"version":3,"file":"api-token.js","sources":["../../../../../server/src/content-types/api-token.ts"],"sourcesContent":["import constants from '../services/constants';\n\nexport default {\n collectionName: 'strapi_api_tokens',\n info: {\n name: 'Api Token',\n singularName: 'api-token',\n pluralName: 'api-tokens',\n displayName: 'Api Token',\n description: '',\n },\n options: {},\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n name: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n unique: true,\n },\n description: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: false,\n default: '',\n },\n type: {\n type: 'enumeration',\n enum: Object.values(constants.API_TOKEN_TYPE),\n configurable: false,\n required: true,\n default: constants.API_TOKEN_TYPE.READ_ONLY,\n },\n accessKey: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n searchable: false,\n },\n encryptedKey: {\n type: 'text',\n minLength: 1,\n configurable: false,\n required: false,\n searchable: false,\n },\n lastUsedAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n permissions: {\n type: 'relation',\n target: 'admin::api-token-permission',\n relation: 'oneToMany',\n mappedBy: 'token',\n configurable: false,\n required: false,\n },\n expiresAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n lifespan: {\n type: 'biginteger',\n configurable: false,\n required: false,\n },\n },\n};\n"],"names":["collectionName","info","name","singularName","pluralName","displayName","description","options","pluginOptions","visible","attributes","type","minLength","configurable","required","unique","default","enum","Object","values","constants","API_TOKEN_TYPE","READ_ONLY","accessKey","searchable","encryptedKey","lastUsedAt","permissions","target","relation","mappedBy","expiresAt","lifespan"],"mappings":";;;;AAEA,eAAe;IACbA,cAAgB,EAAA,mBAAA;IAChBC,IAAM,EAAA;QACJC,IAAM,EAAA,WAAA;QACNC,YAAc,EAAA,WAAA;QACdC,UAAY,EAAA,YAAA;QACZC,WAAa,EAAA,WAAA;QACbC,WAAa,EAAA;AACf,KAAA;AACAC,IAAAA,OAAAA,EAAS,EAAC;IACVC,aAAe,EAAA;QACb,iBAAmB,EAAA;YACjBC,OAAS,EAAA;AACX,SAAA;QACA,sBAAwB,EAAA;YACtBA,OAAS,EAAA;AACX;AACF,KAAA;IACAC,UAAY,EAAA;QACVR,IAAM,EAAA;YACJS,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVC,MAAQ,EAAA;AACV,SAAA;QACAT,WAAa,EAAA;YACXK,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,KAAA;YACVE,OAAS,EAAA;AACX,SAAA;QACAL,IAAM,EAAA;YACJA,IAAM,EAAA,aAAA;AACNM,YAAAA,IAAAA,EAAMC,MAAOC,CAAAA,MAAM,CAACC,SAAAA,CAAUC,cAAc,CAAA;YAC5CR,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVE,OAASI,EAAAA,SAAAA,CAAUC,cAAc,CAACC;AACpC,SAAA;QACAC,SAAW,EAAA;YACTZ,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVU,UAAY,EAAA;AACd,SAAA;QACAC,YAAc,EAAA;YACZd,IAAM,EAAA,MAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,KAAA;YACVU,UAAY,EAAA;AACd,SAAA;QACAE,UAAY,EAAA;YACVf,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAa,WAAa,EAAA;YACXhB,IAAM,EAAA,UAAA;YACNiB,MAAQ,EAAA,6BAAA;YACRC,QAAU,EAAA,WAAA;YACVC,QAAU,EAAA,OAAA;YACVjB,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAiB,SAAW,EAAA;YACTpB,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAkB,QAAU,EAAA;YACRrB,IAAM,EAAA,YAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ;AACF;AACF,CAAE;;;;"}
@@ -47,6 +47,13 @@ var apiToken = {
47
47
  required: true,
48
48
  searchable: false
49
49
  },
50
+ encryptedKey: {
51
+ type: 'text',
52
+ minLength: 1,
53
+ configurable: false,
54
+ required: false,
55
+ searchable: false
56
+ },
50
57
  lastUsedAt: {
51
58
  type: 'datetime',
52
59
  configurable: false,
@@ -1 +1 @@
1
- {"version":3,"file":"api-token.mjs","sources":["../../../../../server/src/content-types/api-token.ts"],"sourcesContent":["import constants from '../services/constants';\n\nexport default {\n collectionName: 'strapi_api_tokens',\n info: {\n name: 'Api Token',\n singularName: 'api-token',\n pluralName: 'api-tokens',\n displayName: 'Api Token',\n description: '',\n },\n options: {},\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n name: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n unique: true,\n },\n description: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: false,\n default: '',\n },\n type: {\n type: 'enumeration',\n enum: Object.values(constants.API_TOKEN_TYPE),\n configurable: false,\n required: true,\n default: constants.API_TOKEN_TYPE.READ_ONLY,\n },\n accessKey: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n searchable: false,\n },\n lastUsedAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n permissions: {\n type: 'relation',\n target: 'admin::api-token-permission',\n relation: 'oneToMany',\n mappedBy: 'token',\n configurable: false,\n required: false,\n },\n expiresAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n lifespan: {\n type: 'biginteger',\n configurable: false,\n required: false,\n },\n },\n};\n"],"names":["collectionName","info","name","singularName","pluralName","displayName","description","options","pluginOptions","visible","attributes","type","minLength","configurable","required","unique","default","enum","Object","values","constants","API_TOKEN_TYPE","READ_ONLY","accessKey","searchable","lastUsedAt","permissions","target","relation","mappedBy","expiresAt","lifespan"],"mappings":";;AAEA,eAAe;IACbA,cAAgB,EAAA,mBAAA;IAChBC,IAAM,EAAA;QACJC,IAAM,EAAA,WAAA;QACNC,YAAc,EAAA,WAAA;QACdC,UAAY,EAAA,YAAA;QACZC,WAAa,EAAA,WAAA;QACbC,WAAa,EAAA;AACf,KAAA;AACAC,IAAAA,OAAAA,EAAS,EAAC;IACVC,aAAe,EAAA;QACb,iBAAmB,EAAA;YACjBC,OAAS,EAAA;AACX,SAAA;QACA,sBAAwB,EAAA;YACtBA,OAAS,EAAA;AACX;AACF,KAAA;IACAC,UAAY,EAAA;QACVR,IAAM,EAAA;YACJS,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVC,MAAQ,EAAA;AACV,SAAA;QACAT,WAAa,EAAA;YACXK,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,KAAA;YACVE,OAAS,EAAA;AACX,SAAA;QACAL,IAAM,EAAA;YACJA,IAAM,EAAA,aAAA;AACNM,YAAAA,IAAAA,EAAMC,MAAOC,CAAAA,MAAM,CAACC,SAAAA,CAAUC,cAAc,CAAA;YAC5CR,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVE,OAASI,EAAAA,SAAAA,CAAUC,cAAc,CAACC;AACpC,SAAA;QACAC,SAAW,EAAA;YACTZ,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVU,UAAY,EAAA;AACd,SAAA;QACAC,UAAY,EAAA;YACVd,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAY,WAAa,EAAA;YACXf,IAAM,EAAA,UAAA;YACNgB,MAAQ,EAAA,6BAAA;YACRC,QAAU,EAAA,WAAA;YACVC,QAAU,EAAA,OAAA;YACVhB,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAgB,SAAW,EAAA;YACTnB,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAiB,QAAU,EAAA;YACRpB,IAAM,EAAA,YAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ;AACF;AACF,CAAE;;;;"}
1
+ {"version":3,"file":"api-token.mjs","sources":["../../../../../server/src/content-types/api-token.ts"],"sourcesContent":["import constants from '../services/constants';\n\nexport default {\n collectionName: 'strapi_api_tokens',\n info: {\n name: 'Api Token',\n singularName: 'api-token',\n pluralName: 'api-tokens',\n displayName: 'Api Token',\n description: '',\n },\n options: {},\n pluginOptions: {\n 'content-manager': {\n visible: false,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n name: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n unique: true,\n },\n description: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: false,\n default: '',\n },\n type: {\n type: 'enumeration',\n enum: Object.values(constants.API_TOKEN_TYPE),\n configurable: false,\n required: true,\n default: constants.API_TOKEN_TYPE.READ_ONLY,\n },\n accessKey: {\n type: 'string',\n minLength: 1,\n configurable: false,\n required: true,\n searchable: false,\n },\n encryptedKey: {\n type: 'text',\n minLength: 1,\n configurable: false,\n required: false,\n searchable: false,\n },\n lastUsedAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n permissions: {\n type: 'relation',\n target: 'admin::api-token-permission',\n relation: 'oneToMany',\n mappedBy: 'token',\n configurable: false,\n required: false,\n },\n expiresAt: {\n type: 'datetime',\n configurable: false,\n required: false,\n },\n lifespan: {\n type: 'biginteger',\n configurable: false,\n required: false,\n },\n },\n};\n"],"names":["collectionName","info","name","singularName","pluralName","displayName","description","options","pluginOptions","visible","attributes","type","minLength","configurable","required","unique","default","enum","Object","values","constants","API_TOKEN_TYPE","READ_ONLY","accessKey","searchable","encryptedKey","lastUsedAt","permissions","target","relation","mappedBy","expiresAt","lifespan"],"mappings":";;AAEA,eAAe;IACbA,cAAgB,EAAA,mBAAA;IAChBC,IAAM,EAAA;QACJC,IAAM,EAAA,WAAA;QACNC,YAAc,EAAA,WAAA;QACdC,UAAY,EAAA,YAAA;QACZC,WAAa,EAAA,WAAA;QACbC,WAAa,EAAA;AACf,KAAA;AACAC,IAAAA,OAAAA,EAAS,EAAC;IACVC,aAAe,EAAA;QACb,iBAAmB,EAAA;YACjBC,OAAS,EAAA;AACX,SAAA;QACA,sBAAwB,EAAA;YACtBA,OAAS,EAAA;AACX;AACF,KAAA;IACAC,UAAY,EAAA;QACVR,IAAM,EAAA;YACJS,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVC,MAAQ,EAAA;AACV,SAAA;QACAT,WAAa,EAAA;YACXK,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,KAAA;YACVE,OAAS,EAAA;AACX,SAAA;QACAL,IAAM,EAAA;YACJA,IAAM,EAAA,aAAA;AACNM,YAAAA,IAAAA,EAAMC,MAAOC,CAAAA,MAAM,CAACC,SAAAA,CAAUC,cAAc,CAAA;YAC5CR,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVE,OAASI,EAAAA,SAAAA,CAAUC,cAAc,CAACC;AACpC,SAAA;QACAC,SAAW,EAAA;YACTZ,IAAM,EAAA,QAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,IAAA;YACVU,UAAY,EAAA;AACd,SAAA;QACAC,YAAc,EAAA;YACZd,IAAM,EAAA,MAAA;YACNC,SAAW,EAAA,CAAA;YACXC,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA,KAAA;YACVU,UAAY,EAAA;AACd,SAAA;QACAE,UAAY,EAAA;YACVf,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAa,WAAa,EAAA;YACXhB,IAAM,EAAA,UAAA;YACNiB,MAAQ,EAAA,6BAAA;YACRC,QAAU,EAAA,WAAA;YACVC,QAAU,EAAA,OAAA;YACVjB,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAiB,SAAW,EAAA;YACTpB,IAAM,EAAA,UAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ,SAAA;QACAkB,QAAU,EAAA;YACRrB,IAAM,EAAA,YAAA;YACNE,YAAc,EAAA,KAAA;YACdC,QAAU,EAAA;AACZ;AACF;AACF,CAAE;;;;"}
@@ -4,6 +4,7 @@ var crypto = require('crypto');
4
4
  var fp = require('lodash/fp');
5
5
  var utils = require('@strapi/utils');
6
6
  var constants = require('./constants.js');
7
+ var index = require('../utils/index.js');
7
8
 
8
9
  const { ValidationError, NotFoundError } = utils.errors;
9
10
  const SELECT_FIELDS = [
@@ -78,14 +79,25 @@ const POPULATE_FIELDS = [
78
79
  return null;
79
80
  }
80
81
  const token = await strapi.db.query('admin::api-token').findOne({
81
- select: SELECT_FIELDS,
82
+ select: [
83
+ ...SELECT_FIELDS,
84
+ 'encryptedKey'
85
+ ],
82
86
  populate: POPULATE_FIELDS,
83
87
  where: whereParams
84
88
  });
85
89
  if (!token) {
86
90
  return token;
87
91
  }
88
- return flattenTokenPermissions(token);
92
+ const { encryptedKey, ...rest } = token;
93
+ if (!encryptedKey) {
94
+ return flattenTokenPermissions(rest);
95
+ }
96
+ const accessKey = index.getService('encryption').decrypt(encryptedKey);
97
+ return flattenTokenPermissions({
98
+ ...rest,
99
+ accessKey
100
+ });
89
101
  };
90
102
  /**
91
103
  * Check if token exists
@@ -112,7 +124,9 @@ const getExpirationFields = (lifespan)=>{
112
124
  /**
113
125
  * Create a token and its permissions
114
126
  */ const create = async (attributes)=>{
127
+ const encryptionService = index.getService('encryption');
115
128
  const accessKey = crypto.randomBytes(128).toString('hex');
129
+ const encryptedKey = encryptionService.encrypt(accessKey);
116
130
  assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);
117
131
  assertValidLifespan(attributes.lifespan);
118
132
  // Create the token
@@ -122,6 +136,7 @@ const getExpirationFields = (lifespan)=>{
122
136
  data: {
123
137
  ...fp.omit('permissions', attributes),
124
138
  accessKey: hash(accessKey),
139
+ encryptedKey,
125
140
  ...getExpirationFields(attributes.lifespan)
126
141
  }
127
142
  });
@@ -153,6 +168,8 @@ const getExpirationFields = (lifespan)=>{
153
168
  };
154
169
  const regenerate = async (id)=>{
155
170
  const accessKey = crypto.randomBytes(128).toString('hex');
171
+ const encryptionService = index.getService('encryption');
172
+ const encryptedKey = encryptionService.encrypt(accessKey);
156
173
  const apiToken = await strapi.db.query('admin::api-token').update({
157
174
  select: [
158
175
  'id',
@@ -162,7 +179,8 @@ const regenerate = async (id)=>{
162
179
  id
163
180
  },
164
181
  data: {
165
- accessKey: hash(accessKey)
182
+ accessKey: hash(accessKey),
183
+ encryptedKey
166
184
  }
167
185
  });
168
186
  if (!apiToken) {
@@ -1 +1 @@
1
- {"version":3,"file":"api-token.js","sources":["../../../../../server/src/services/api-token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { omit, difference, isNil, isEmpty, map, isArray, uniq, isNumber } from 'lodash/fp';\nimport { errors } from '@strapi/utils';\nimport type { Update, ApiToken, ApiTokenBody } from '../../../shared/contracts/api-token';\nimport constants from './constants';\n\nconst { ValidationError, NotFoundError } = errors;\n\ntype ApiTokenPermission = {\n id: number | `${number}`;\n action: string;\n token: DBApiToken | number;\n};\n\ntype DBApiToken = ApiToken & {\n permissions: (number | ApiTokenPermission)[];\n};\n\nconst SELECT_FIELDS = [\n 'id',\n 'name',\n 'description',\n 'lastUsedAt',\n 'type',\n 'lifespan',\n 'expiresAt',\n 'createdAt',\n 'updatedAt',\n];\n\nconst POPULATE_FIELDS = ['permissions'];\n\n// TODO: we need to ensure the permissions are actually valid registered permissions!\n\n/**\n * Assert that a token's permissions attribute is valid for its type\n */\nconst assertCustomTokenPermissionsValidity = (\n type: ApiTokenBody['type'],\n permissions: ApiTokenBody['permissions']\n) => {\n // Ensure non-custom tokens doesn't have permissions\n if (type !== constants.API_TOKEN_TYPE.CUSTOM && !isEmpty(permissions)) {\n throw new ValidationError('Non-custom tokens should not reference permissions');\n }\n\n // Custom type tokens should always have permissions attached to them\n if (type === constants.API_TOKEN_TYPE.CUSTOM && !isArray(permissions)) {\n throw new ValidationError('Missing permissions attribute for custom token');\n }\n\n // Permissions provided for a custom type token should be valid/registered permissions UID\n if (type === constants.API_TOKEN_TYPE.CUSTOM) {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const invalidPermissions = difference(permissions, validPermissions) as string[];\n\n if (!isEmpty(invalidPermissions)) {\n throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);\n }\n }\n};\n\n/**\n * Check if a token's lifespan is valid\n */\nconst isValidLifespan = (lifespan: unknown) => {\n if (isNil(lifespan)) {\n return true;\n }\n\n if (!isNumber(lifespan) || !Object.values(constants.API_TOKEN_LIFESPANS).includes(lifespan)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Assert that a token's lifespan is valid\n */\nconst assertValidLifespan = (lifespan: unknown) => {\n if (!isValidLifespan(lifespan)) {\n throw new ValidationError(\n `lifespan must be one of the following values:\n ${Object.values(constants.API_TOKEN_LIFESPANS).join(', ')}`\n );\n }\n};\n\n/**\n * Flatten a token's database permissions objects to an array of strings\n */\nconst flattenTokenPermissions = (token: DBApiToken): ApiToken => {\n if (!token) {\n return token;\n }\n\n return {\n ...token,\n permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,\n };\n};\n\ntype WhereParams = {\n id?: string | number;\n name?: string;\n lastUsedAt?: number;\n description?: string;\n accessKey?: string;\n};\n\n/**\n * Get a token\n */\nconst getBy = async (whereParams: WhereParams = {}): Promise<ApiToken | null> => {\n if (Object.keys(whereParams).length === 0) {\n return null;\n }\n\n const token = await strapi.db\n .query('admin::api-token')\n .findOne({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: whereParams });\n\n if (!token) {\n return token;\n }\n\n return flattenTokenPermissions(token);\n};\n\n/**\n * Check if token exists\n */\nconst exists = async (whereParams: WhereParams = {}): Promise<boolean> => {\n const apiToken = await getBy(whereParams);\n\n return !!apiToken;\n};\n\n/**\n * Return a secure sha512 hash of an accessKey\n */\nconst hash = (accessKey: string) => {\n return crypto\n .createHmac('sha512', strapi.config.get('admin.apiToken.salt'))\n .update(accessKey)\n .digest('hex');\n};\n\nconst getExpirationFields = (lifespan: ApiTokenBody['lifespan']) => {\n // it must be nil or a finite number >= 0\n const isValidNumber = isNumber(lifespan) && Number.isFinite(lifespan) && lifespan > 0;\n if (!isValidNumber && !isNil(lifespan)) {\n throw new ValidationError('lifespan must be a positive number or null');\n }\n\n return {\n lifespan: lifespan || null,\n expiresAt: lifespan ? Date.now() + lifespan : null,\n };\n};\n\n/**\n * Create a token and its permissions\n */\nconst create = async (attributes: ApiTokenBody): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n\n assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);\n assertValidLifespan(attributes.lifespan);\n\n // Create the token\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').create({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n data: {\n ...omit('permissions', attributes),\n accessKey: hash(accessKey),\n ...getExpirationFields(attributes.lifespan),\n },\n });\n\n const result: ApiToken = { ...apiToken, accessKey };\n\n // If this is a custom type token, create and the related permissions\n if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {\n // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries\n // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({\n // populate: POPULATE_FIELDS,\n // data: attributes.permissions.map(action => ({ action, token: apiToken })),\n // });\n await Promise.all(\n uniq(attributes.permissions).map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: apiToken },\n })\n )\n );\n\n const currentPermissions = await strapi.db\n .query('admin::api-token')\n .load(apiToken, 'permissions');\n\n if (currentPermissions) {\n Object.assign(result, { permissions: map('action', currentPermissions) });\n }\n }\n\n return result;\n};\n\nconst regenerate = async (id: string | number): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: ['id', 'accessKey'],\n where: { id },\n data: {\n accessKey: hash(accessKey),\n },\n });\n\n if (!apiToken) {\n throw new NotFoundError('The provided token id does not exist');\n }\n\n return {\n ...apiToken,\n accessKey,\n };\n};\n\nconst checkSaltIsDefined = () => {\n if (!strapi.config.get('admin.apiToken.salt')) {\n // TODO V5: stop reading API_TOKEN_SALT\n if (process.env.API_TOKEN_SALT) {\n process.emitWarning(`[deprecated] In future versions, Strapi will stop reading directly from the environment variable API_TOKEN_SALT. Please set apiToken.salt in config/admin.js instead.\nFor security reasons, keep storing the secret in an environment variable and use env() to read it in config/admin.js (ex: \\`apiToken: { salt: env('API_TOKEN_SALT') }\\`). See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);\n\n strapi.config.set('admin.apiToken.salt', process.env.API_TOKEN_SALT);\n } else {\n throw new Error(\n `Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n }\n};\n\n/**\n * Return a list of all tokens and their permissions\n */\nconst list = async (): Promise<Array<ApiToken>> => {\n const tokens: Array<DBApiToken> = await strapi.db.query('admin::api-token').findMany({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n orderBy: { name: 'ASC' },\n });\n\n if (!tokens) {\n return tokens;\n }\n\n return tokens.map((token) => flattenTokenPermissions(token));\n};\n\n/**\n * Revoke (delete) a token\n */\nconst revoke = async (id: string | number): Promise<ApiToken> => {\n return strapi.db\n .query('admin::api-token')\n .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } });\n};\n\n/**\n * Retrieve a token by id\n */\nconst getById = async (id: string | number) => {\n return getBy({ id });\n};\n\n/**\n * Retrieve a token by name\n */\nconst getByName = async (name: string) => {\n return getBy({ name });\n};\n\n/**\n * Update a token and its permissions\n */\nconst update = async (\n id: string | number,\n attributes: Update.Request['body']\n): Promise<ApiToken> => {\n // retrieve token without permissions\n const originalToken: DBApiToken = await strapi.db\n .query('admin::api-token')\n .findOne({ where: { id } });\n\n if (!originalToken) {\n throw new NotFoundError('Token not found');\n }\n\n const changingTypeToCustom =\n attributes.type === constants.API_TOKEN_TYPE.CUSTOM &&\n originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;\n\n // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid\n // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update\n if (attributes.permissions || changingTypeToCustom) {\n assertCustomTokenPermissionsValidity(\n attributes.type || originalToken.type,\n attributes.permissions || originalToken.permissions\n );\n }\n\n assertValidLifespan(attributes.lifespan);\n\n const updatedToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: SELECT_FIELDS,\n where: { id },\n data: omit('permissions', attributes),\n });\n\n // custom tokens need to have their permissions updated as well\n if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {\n const currentPermissionsResult = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n const currentPermissions = map('action', currentPermissionsResult || []);\n const newPermissions = uniq(attributes.permissions);\n\n const actionsToDelete = difference(currentPermissions, newPermissions);\n const actionsToAdd = difference(newPermissions, currentPermissions);\n\n // TODO: improve efficiency here\n // method using a loop -- works but very inefficient\n await Promise.all(\n actionsToDelete.map((action) =>\n strapi.db.query('admin::api-token-permission').delete({\n where: { action, token: id },\n })\n )\n );\n\n // TODO: improve efficiency here\n // using a loop -- works but very inefficient\n await Promise.all(\n actionsToAdd.map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: id },\n })\n )\n );\n }\n // if type is not custom, make sure any old permissions get removed\n else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {\n await strapi.db.query('admin::api-token-permission').delete({\n where: { token: id },\n });\n }\n\n // retrieve permissions\n const permissionsFromDb = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n return {\n ...updatedToken,\n permissions: permissionsFromDb ? permissionsFromDb.map((p: any) => p.action) : undefined,\n };\n};\n\nconst count = async (where = {}): Promise<number> => {\n return strapi.db.query('admin::api-token').count({ where });\n};\n\nexport {\n create,\n count,\n regenerate,\n exists,\n checkSaltIsDefined,\n hash,\n list,\n revoke,\n getById,\n update,\n getByName,\n getBy,\n};\n"],"names":["ValidationError","NotFoundError","errors","SELECT_FIELDS","POPULATE_FIELDS","assertCustomTokenPermissionsValidity","type","permissions","constants","API_TOKEN_TYPE","CUSTOM","isEmpty","isArray","validPermissions","strapi","contentAPI","providers","action","keys","invalidPermissions","difference","join","isValidLifespan","lifespan","isNil","isNumber","Object","values","API_TOKEN_LIFESPANS","includes","assertValidLifespan","flattenTokenPermissions","token","map","getBy","whereParams","length","db","query","findOne","select","populate","where","exists","apiToken","hash","accessKey","crypto","createHmac","config","get","update","digest","getExpirationFields","isValidNumber","Number","isFinite","expiresAt","Date","now","create","attributes","randomBytes","toString","data","omit","result","Promise","all","uniq","currentPermissions","load","assign","regenerate","id","checkSaltIsDefined","process","env","API_TOKEN_SALT","emitWarning","set","Error","list","tokens","findMany","orderBy","name","revoke","delete","getById","getByName","originalToken","changingTypeToCustom","updatedToken","currentPermissionsResult","newPermissions","actionsToDelete","actionsToAdd","permissionsFromDb","p","undefined","count"],"mappings":";;;;;;;AAMA,MAAM,EAAEA,eAAe,EAAEC,aAAa,EAAE,GAAGC,YAAAA;AAY3C,MAAMC,aAAgB,GAAA;AACpB,IAAA,IAAA;AACA,IAAA,MAAA;AACA,IAAA,aAAA;AACA,IAAA,YAAA;AACA,IAAA,MAAA;AACA,IAAA,UAAA;AACA,IAAA,WAAA;AACA,IAAA,WAAA;AACA,IAAA;AACD,CAAA;AAED,MAAMC,eAAkB,GAAA;AAAC,IAAA;AAAc,CAAA;AAEvC;AAEA;;IAGA,MAAMC,oCAAuC,GAAA,CAC3CC,IACAC,EAAAA,WAAAA,GAAAA;;IAGA,IAAID,IAAAA,KAASE,UAAUC,cAAc,CAACC,MAAM,IAAI,CAACC,WAAQJ,WAAc,CAAA,EAAA;AACrE,QAAA,MAAM,IAAIP,eAAgB,CAAA,oDAAA,CAAA;AAC5B;;IAGA,IAAIM,IAAAA,KAASE,UAAUC,cAAc,CAACC,MAAM,IAAI,CAACE,WAAQL,WAAc,CAAA,EAAA;AACrE,QAAA,MAAM,IAAIP,eAAgB,CAAA,gDAAA,CAAA;AAC5B;;AAGA,IAAA,IAAIM,IAASE,KAAAA,SAAAA,CAAUC,cAAc,CAACC,MAAM,EAAE;QAC5C,MAAMG,gBAAAA,GAAmBC,MAAOC,CAAAA,UAAU,CAACR,WAAW,CAACS,SAAS,CAACC,MAAM,CAACC,IAAI,EAAA;QAC5E,MAAMC,kBAAAA,GAAqBC,cAAWb,WAAaM,EAAAA,gBAAAA,CAAAA;QAEnD,IAAI,CAACF,WAAQQ,kBAAqB,CAAA,EAAA;YAChC,MAAM,IAAInB,gBAAgB,CAAC,8BAA8B,EAAEmB,kBAAmBE,CAAAA,IAAI,CAAC,IAAA,CAAA,CAAM,CAAC,CAAA;AAC5F;AACF;AACF,CAAA;AAEA;;IAGA,MAAMC,kBAAkB,CAACC,QAAAA,GAAAA;AACvB,IAAA,IAAIC,SAAMD,QAAW,CAAA,EAAA;QACnB,OAAO,IAAA;AACT;AAEA,IAAA,IAAI,CAACE,WAAAA,CAASF,QAAa,CAAA,IAAA,CAACG,MAAOC,CAAAA,MAAM,CAACnB,SAAAA,CAAUoB,mBAAmB,CAAA,CAAEC,QAAQ,CAACN,QAAW,CAAA,EAAA;QAC3F,OAAO,KAAA;AACT;IAEA,OAAO,IAAA;AACT,CAAA;AAEA;;IAGA,MAAMO,sBAAsB,CAACP,QAAAA,GAAAA;IAC3B,IAAI,CAACD,gBAAgBC,QAAW,CAAA,EAAA;QAC9B,MAAM,IAAIvB,gBACR,CAAC;MACD,EAAE0B,MAAAA,CAAOC,MAAM,CAACnB,SAAAA,CAAUoB,mBAAmB,CAAEP,CAAAA,IAAI,CAAC,IAAA,CAAA,CAAM,CAAC,CAAA;AAE/D;AACF,CAAA;AAEA;;IAGA,MAAMU,0BAA0B,CAACC,KAAAA,GAAAA;AAC/B,IAAA,IAAI,CAACA,KAAO,EAAA;QACV,OAAOA,KAAAA;AACT;IAEA,OAAO;AACL,QAAA,GAAGA,KAAK;QACRzB,WAAaK,EAAAA,UAAAA,CAAQoB,KAAMzB,CAAAA,WAAW,CAAI0B,GAAAA,MAAAA,CAAI,UAAUD,KAAMzB,CAAAA,WAAW,CAAIyB,GAAAA,KAAAA,CAAMzB;AACrF,KAAA;AACF,CAAA;AAUA;;AAEC,IACK2B,MAAAA,KAAAA,GAAQ,OAAOC,WAAAA,GAA2B,EAAE,GAAA;AAChD,IAAA,IAAIT,OAAOR,IAAI,CAACiB,WAAaC,CAAAA,CAAAA,MAAM,KAAK,CAAG,EAAA;QACzC,OAAO,IAAA;AACT;IAEA,MAAMJ,KAAAA,GAAQ,MAAMlB,MAAOuB,CAAAA,EAAE,CAC1BC,KAAK,CAAC,kBACNC,CAAAA,CAAAA,OAAO,CAAC;QAAEC,MAAQrC,EAAAA,aAAAA;QAAesC,QAAUrC,EAAAA,eAAAA;QAAiBsC,KAAOP,EAAAA;AAAY,KAAA,CAAA;AAElF,IAAA,IAAI,CAACH,KAAO,EAAA;QACV,OAAOA,KAAAA;AACT;AAEA,IAAA,OAAOD,uBAAwBC,CAAAA,KAAAA,CAAAA;AACjC;AAEA;;AAEC,IACKW,MAAAA,MAAAA,GAAS,OAAOR,WAAAA,GAA2B,EAAE,GAAA;IACjD,MAAMS,QAAAA,GAAW,MAAMV,KAAMC,CAAAA,WAAAA,CAAAA;AAE7B,IAAA,OAAO,CAAC,CAACS,QAAAA;AACX;AAEA;;IAGA,MAAMC,OAAO,CAACC,SAAAA,GAAAA;AACZ,IAAA,OAAOC,MACJC,CAAAA,UAAU,CAAC,QAAA,EAAUlC,OAAOmC,MAAM,CAACC,GAAG,CAAC,qBACvCC,CAAAA,CAAAA,CAAAA,MAAM,CAACL,SAAAA,CAAAA,CACPM,MAAM,CAAC,KAAA,CAAA;AACZ;AAEA,MAAMC,sBAAsB,CAAC9B,QAAAA,GAAAA;;AAE3B,IAAA,MAAM+B,gBAAgB7B,WAASF,CAAAA,QAAAA,CAAAA,IAAagC,OAAOC,QAAQ,CAACjC,aAAaA,QAAW,GAAA,CAAA;AACpF,IAAA,IAAI,CAAC+B,aAAAA,IAAiB,CAAC9B,QAAAA,CAAMD,QAAW,CAAA,EAAA;AACtC,QAAA,MAAM,IAAIvB,eAAgB,CAAA,4CAAA,CAAA;AAC5B;IAEA,OAAO;AACLuB,QAAAA,QAAAA,EAAUA,QAAY,IAAA,IAAA;AACtBkC,QAAAA,SAAAA,EAAWlC,QAAWmC,GAAAA,IAAAA,CAAKC,GAAG,EAAA,GAAKpC,QAAW,GAAA;AAChD,KAAA;AACF,CAAA;AAEA;;IAGA,MAAMqC,SAAS,OAAOC,UAAAA,GAAAA;AACpB,IAAA,MAAMf,YAAYC,MAAOe,CAAAA,WAAW,CAAC,GAAA,CAAA,CAAKC,QAAQ,CAAC,KAAA,CAAA;AAEnD1D,IAAAA,oCAAAA,CAAqCwD,UAAWvD,CAAAA,IAAI,EAAEuD,UAAAA,CAAWtD,WAAW,CAAA;AAC5EuB,IAAAA,mBAAAA,CAAoB+B,WAAWtC,QAAQ,CAAA;;IAGvC,MAAMqB,QAAAA,GAAqB,MAAM9B,MAAOuB,CAAAA,EAAE,CAACC,KAAK,CAAC,kBAAoBsB,CAAAA,CAAAA,MAAM,CAAC;QAC1EpB,MAAQrC,EAAAA,aAAAA;QACRsC,QAAUrC,EAAAA,eAAAA;QACV4D,IAAM,EAAA;YACJ,GAAGC,OAAAA,CAAK,eAAeJ,UAAW,CAAA;AAClCf,YAAAA,SAAAA,EAAWD,IAAKC,CAAAA,SAAAA,CAAAA;YAChB,GAAGO,mBAAAA,CAAoBQ,UAAWtC,CAAAA,QAAQ;AAC5C;AACF,KAAA,CAAA;AAEA,IAAA,MAAM2C,MAAmB,GAAA;AAAE,QAAA,GAAGtB,QAAQ;AAAEE,QAAAA;AAAU,KAAA;;AAGlD,IAAA,IAAIe,WAAWvD,IAAI,KAAKE,UAAUC,cAAc,CAACC,MAAM,EAAE;;;;;;AAMvD,QAAA,MAAMyD,QAAQC,GAAG,CACfC,QAAKR,UAAWtD,CAAAA,WAAW,EAAE0B,GAAG,CAAC,CAAChB,MAAAA,GAChCH,OAAOuB,EAAE,CAACC,KAAK,CAAC,6BAAA,CAAA,CAA+BsB,MAAM,CAAC;gBACpDI,IAAM,EAAA;AAAE/C,oBAAAA,MAAAA;oBAAQe,KAAOY,EAAAA;AAAS;AAClC,aAAA,CAAA,CAAA,CAAA;QAIJ,MAAM0B,kBAAAA,GAAqB,MAAMxD,MAAAA,CAAOuB,EAAE,CACvCC,KAAK,CAAC,kBAAA,CAAA,CACNiC,IAAI,CAAC3B,QAAU,EAAA,aAAA,CAAA;AAElB,QAAA,IAAI0B,kBAAoB,EAAA;YACtB5C,MAAO8C,CAAAA,MAAM,CAACN,MAAQ,EAAA;AAAE3D,gBAAAA,WAAAA,EAAa0B,OAAI,QAAUqC,EAAAA,kBAAAA;AAAoB,aAAA,CAAA;AACzE;AACF;IAEA,OAAOJ,MAAAA;AACT;AAEA,MAAMO,aAAa,OAAOC,EAAAA,GAAAA;AACxB,IAAA,MAAM5B,YAAYC,MAAOe,CAAAA,WAAW,CAAC,GAAA,CAAA,CAAKC,QAAQ,CAAC,KAAA,CAAA;IAEnD,MAAMnB,QAAAA,GAAqB,MAAM9B,MAAOuB,CAAAA,EAAE,CAACC,KAAK,CAAC,kBAAoBa,CAAAA,CAAAA,MAAM,CAAC;QAC1EX,MAAQ,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA;AAAY,SAAA;QAC3BE,KAAO,EAAA;AAAEgC,YAAAA;AAAG,SAAA;QACZV,IAAM,EAAA;AACJlB,YAAAA,SAAAA,EAAWD,IAAKC,CAAAA,SAAAA;AAClB;AACF,KAAA,CAAA;AAEA,IAAA,IAAI,CAACF,QAAU,EAAA;AACb,QAAA,MAAM,IAAI3C,aAAc,CAAA,sCAAA,CAAA;AAC1B;IAEA,OAAO;AACL,QAAA,GAAG2C,QAAQ;AACXE,QAAAA;AACF,KAAA;AACF;AAEA,MAAM6B,kBAAqB,GAAA,IAAA;AACzB,IAAA,IAAI,CAAC7D,MAAOmC,CAAAA,MAAM,CAACC,GAAG,CAAC,qBAAwB,CAAA,EAAA;;AAE7C,QAAA,IAAI0B,OAAQC,CAAAA,GAAG,CAACC,cAAc,EAAE;YAC9BF,OAAQG,CAAAA,WAAW,CAAC,CAAC;sUAC2S,CAAC,CAAA;YAEjUjE,MAAOmC,CAAAA,MAAM,CAAC+B,GAAG,CAAC,uBAAuBJ,OAAQC,CAAAA,GAAG,CAACC,cAAc,CAAA;SAC9D,MAAA;YACL,MAAM,IAAIG,MACR,CAAC;uQAC8P,CAAC,CAAA;AAEpQ;AACF;AACF;AAEA;;AAEC,UACKC,IAAO,GAAA,UAAA;IACX,MAAMC,MAAAA,GAA4B,MAAMrE,MAAOuB,CAAAA,EAAE,CAACC,KAAK,CAAC,kBAAoB8C,CAAAA,CAAAA,QAAQ,CAAC;QACnF5C,MAAQrC,EAAAA,aAAAA;QACRsC,QAAUrC,EAAAA,eAAAA;QACViF,OAAS,EAAA;YAAEC,IAAM,EAAA;AAAM;AACzB,KAAA,CAAA;AAEA,IAAA,IAAI,CAACH,MAAQ,EAAA;QACX,OAAOA,MAAAA;AACT;AAEA,IAAA,OAAOA,MAAOlD,CAAAA,GAAG,CAAC,CAACD,QAAUD,uBAAwBC,CAAAA,KAAAA,CAAAA,CAAAA;AACvD;AAEA;;IAGA,MAAMuD,SAAS,OAAOb,EAAAA,GAAAA;AACpB,IAAA,OAAO5D,OAAOuB,EAAE,CACbC,KAAK,CAAC,kBAAA,CAAA,CACNkD,MAAM,CAAC;QAAEhD,MAAQrC,EAAAA,aAAAA;QAAesC,QAAUrC,EAAAA,eAAAA;QAAiBsC,KAAO,EAAA;AAAEgC,YAAAA;AAAG;AAAE,KAAA,CAAA;AAC9E;AAEA;;IAGA,MAAMe,UAAU,OAAOf,EAAAA,GAAAA;AACrB,IAAA,OAAOxC,KAAM,CAAA;AAAEwC,QAAAA;AAAG,KAAA,CAAA;AACpB;AAEA;;IAGA,MAAMgB,YAAY,OAAOJ,IAAAA,GAAAA;AACvB,IAAA,OAAOpD,KAAM,CAAA;AAAEoD,QAAAA;AAAK,KAAA,CAAA;AACtB;AAEA;;IAGA,MAAMnC,MAAS,GAAA,OACbuB,EACAb,EAAAA,UAAAA,GAAAA;;IAGA,MAAM8B,aAAAA,GAA4B,MAAM7E,MAAOuB,CAAAA,EAAE,CAC9CC,KAAK,CAAC,kBACNC,CAAAA,CAAAA,OAAO,CAAC;QAAEG,KAAO,EAAA;AAAEgC,YAAAA;AAAG;AAAE,KAAA,CAAA;AAE3B,IAAA,IAAI,CAACiB,aAAe,EAAA;AAClB,QAAA,MAAM,IAAI1F,aAAc,CAAA,iBAAA,CAAA;AAC1B;AAEA,IAAA,MAAM2F,oBACJ/B,GAAAA,UAAAA,CAAWvD,IAAI,KAAKE,UAAUC,cAAc,CAACC,MAAM,IACnDiF,cAAcrF,IAAI,KAAKE,SAAUC,CAAAA,cAAc,CAACC,MAAM;;;IAIxD,IAAImD,UAAAA,CAAWtD,WAAW,IAAIqF,oBAAsB,EAAA;QAClDvF,oCACEwD,CAAAA,UAAAA,CAAWvD,IAAI,IAAIqF,aAAcrF,CAAAA,IAAI,EACrCuD,UAAWtD,CAAAA,WAAW,IAAIoF,aAAAA,CAAcpF,WAAW,CAAA;AAEvD;AAEAuB,IAAAA,mBAAAA,CAAoB+B,WAAWtC,QAAQ,CAAA;IAEvC,MAAMsE,YAAAA,GAAyB,MAAM/E,MAAOuB,CAAAA,EAAE,CAACC,KAAK,CAAC,kBAAoBa,CAAAA,CAAAA,MAAM,CAAC;QAC9EX,MAAQrC,EAAAA,aAAAA;QACRuC,KAAO,EAAA;AAAEgC,YAAAA;AAAG,SAAA;AACZV,QAAAA,IAAAA,EAAMC,QAAK,aAAeJ,EAAAA,UAAAA;AAC5B,KAAA,CAAA;;IAGA,IAAIgC,YAAAA,CAAavF,IAAI,KAAKE,SAAUC,CAAAA,cAAc,CAACC,MAAM,IAAImD,UAAWtD,CAAAA,WAAW,EAAE;QACnF,MAAMuF,wBAAAA,GAA2B,MAAMhF,MAAAA,CAAOuB,EAAE,CAC7CC,KAAK,CAAC,kBAAA,CAAA,CACNiC,IAAI,CAACsB,YAAc,EAAA,aAAA,CAAA;AAEtB,QAAA,MAAMvB,kBAAqBrC,GAAAA,MAAAA,CAAI,QAAU6D,EAAAA,wBAAAA,IAA4B,EAAE,CAAA;QACvE,MAAMC,cAAAA,GAAiB1B,OAAKR,CAAAA,UAAAA,CAAWtD,WAAW,CAAA;QAElD,MAAMyF,eAAAA,GAAkB5E,cAAWkD,kBAAoByB,EAAAA,cAAAA,CAAAA;QACvD,MAAME,YAAAA,GAAe7E,cAAW2E,cAAgBzB,EAAAA,kBAAAA,CAAAA;;;AAIhD,QAAA,MAAMH,OAAQC,CAAAA,GAAG,CACf4B,eAAAA,CAAgB/D,GAAG,CAAC,CAAChB,MACnBH,GAAAA,MAAAA,CAAOuB,EAAE,CAACC,KAAK,CAAC,6BAAA,CAAA,CAA+BkD,MAAM,CAAC;gBACpD9C,KAAO,EAAA;AAAEzB,oBAAAA,MAAAA;oBAAQe,KAAO0C,EAAAA;AAAG;AAC7B,aAAA,CAAA,CAAA,CAAA;;;AAMJ,QAAA,MAAMP,OAAQC,CAAAA,GAAG,CACf6B,YAAAA,CAAahE,GAAG,CAAC,CAAChB,MAChBH,GAAAA,MAAAA,CAAOuB,EAAE,CAACC,KAAK,CAAC,6BAAA,CAAA,CAA+BsB,MAAM,CAAC;gBACpDI,IAAM,EAAA;AAAE/C,oBAAAA,MAAAA;oBAAQe,KAAO0C,EAAAA;AAAG;AAC5B,aAAA,CAAA,CAAA,CAAA;KAKD,MAAA,IAAImB,aAAavF,IAAI,KAAKE,UAAUC,cAAc,CAACC,MAAM,EAAE;AAC9D,QAAA,MAAMI,OAAOuB,EAAE,CAACC,KAAK,CAAC,6BAAA,CAAA,CAA+BkD,MAAM,CAAC;YAC1D9C,KAAO,EAAA;gBAAEV,KAAO0C,EAAAA;AAAG;AACrB,SAAA,CAAA;AACF;;IAGA,MAAMwB,iBAAAA,GAAoB,MAAMpF,MAAAA,CAAOuB,EAAE,CACtCC,KAAK,CAAC,kBAAA,CAAA,CACNiC,IAAI,CAACsB,YAAc,EAAA,aAAA,CAAA;IAEtB,OAAO;AACL,QAAA,GAAGA,YAAY;QACftF,WAAa2F,EAAAA,iBAAAA,GAAoBA,kBAAkBjE,GAAG,CAAC,CAACkE,CAAWA,GAAAA,CAAAA,CAAElF,MAAM,CAAImF,GAAAA;AACjF,KAAA;AACF;AAEA,MAAMC,KAAQ,GAAA,OAAO3D,KAAQ,GAAA,EAAE,GAAA;AAC7B,IAAA,OAAO5B,OAAOuB,EAAE,CAACC,KAAK,CAAC,kBAAA,CAAA,CAAoB+D,KAAK,CAAC;AAAE3D,QAAAA;AAAM,KAAA,CAAA;AAC3D;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"api-token.js","sources":["../../../../../server/src/services/api-token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { omit, difference, isNil, isEmpty, map, isArray, uniq, isNumber } from 'lodash/fp';\nimport { errors } from '@strapi/utils';\nimport type { Update, ApiToken, ApiTokenBody } from '../../../shared/contracts/api-token';\nimport constants from './constants';\nimport { getService } from '../utils';\n\nconst { ValidationError, NotFoundError } = errors;\n\ntype ApiTokenPermission = {\n id: number | `${number}`;\n action: string;\n token: DBApiToken | number;\n};\n\ntype DBApiToken = ApiToken & {\n permissions: (number | ApiTokenPermission)[];\n};\n\nconst SELECT_FIELDS = [\n 'id',\n 'name',\n 'description',\n 'lastUsedAt',\n 'type',\n 'lifespan',\n 'expiresAt',\n 'createdAt',\n 'updatedAt',\n];\n\nconst POPULATE_FIELDS = ['permissions'];\n\n// TODO: we need to ensure the permissions are actually valid registered permissions!\n\n/**\n * Assert that a token's permissions attribute is valid for its type\n */\nconst assertCustomTokenPermissionsValidity = (\n type: ApiTokenBody['type'],\n permissions: ApiTokenBody['permissions']\n) => {\n // Ensure non-custom tokens doesn't have permissions\n if (type !== constants.API_TOKEN_TYPE.CUSTOM && !isEmpty(permissions)) {\n throw new ValidationError('Non-custom tokens should not reference permissions');\n }\n\n // Custom type tokens should always have permissions attached to them\n if (type === constants.API_TOKEN_TYPE.CUSTOM && !isArray(permissions)) {\n throw new ValidationError('Missing permissions attribute for custom token');\n }\n\n // Permissions provided for a custom type token should be valid/registered permissions UID\n if (type === constants.API_TOKEN_TYPE.CUSTOM) {\n const validPermissions = strapi.contentAPI.permissions.providers.action.keys();\n const invalidPermissions = difference(permissions, validPermissions) as string[];\n\n if (!isEmpty(invalidPermissions)) {\n throw new ValidationError(`Unknown permissions provided: ${invalidPermissions.join(', ')}`);\n }\n }\n};\n\n/**\n * Check if a token's lifespan is valid\n */\nconst isValidLifespan = (lifespan: unknown) => {\n if (isNil(lifespan)) {\n return true;\n }\n\n if (!isNumber(lifespan) || !Object.values(constants.API_TOKEN_LIFESPANS).includes(lifespan)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Assert that a token's lifespan is valid\n */\nconst assertValidLifespan = (lifespan: unknown) => {\n if (!isValidLifespan(lifespan)) {\n throw new ValidationError(\n `lifespan must be one of the following values:\n ${Object.values(constants.API_TOKEN_LIFESPANS).join(', ')}`\n );\n }\n};\n\n/**\n * Flatten a token's database permissions objects to an array of strings\n */\nconst flattenTokenPermissions = (token: DBApiToken): ApiToken => {\n if (!token) {\n return token;\n }\n\n return {\n ...token,\n permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions,\n };\n};\n\ntype WhereParams = {\n id?: string | number;\n name?: string;\n lastUsedAt?: number;\n description?: string;\n accessKey?: string;\n};\n\n/**\n * Get a token\n */\nconst getBy = async (whereParams: WhereParams = {}): Promise<ApiToken | null> => {\n if (Object.keys(whereParams).length === 0) {\n return null;\n }\n\n const token = await strapi.db.query('admin::api-token').findOne({\n select: [...SELECT_FIELDS, 'encryptedKey'],\n populate: POPULATE_FIELDS,\n where: whereParams,\n });\n\n if (!token) {\n return token;\n }\n\n const { encryptedKey, ...rest } = token;\n\n if (!encryptedKey) {\n return flattenTokenPermissions(rest);\n }\n\n const accessKey = getService('encryption').decrypt(encryptedKey);\n\n return flattenTokenPermissions({\n ...rest,\n accessKey,\n });\n};\n\n/**\n * Check if token exists\n */\nconst exists = async (whereParams: WhereParams = {}): Promise<boolean> => {\n const apiToken = await getBy(whereParams);\n\n return !!apiToken;\n};\n\n/**\n * Return a secure sha512 hash of an accessKey\n */\nconst hash = (accessKey: string) => {\n return crypto\n .createHmac('sha512', strapi.config.get('admin.apiToken.salt'))\n .update(accessKey)\n .digest('hex');\n};\n\nconst getExpirationFields = (lifespan: ApiTokenBody['lifespan']) => {\n // it must be nil or a finite number >= 0\n const isValidNumber = isNumber(lifespan) && Number.isFinite(lifespan) && lifespan > 0;\n if (!isValidNumber && !isNil(lifespan)) {\n throw new ValidationError('lifespan must be a positive number or null');\n }\n\n return {\n lifespan: lifespan || null,\n expiresAt: lifespan ? Date.now() + lifespan : null,\n };\n};\n\n/**\n * Create a token and its permissions\n */\nconst create = async (attributes: ApiTokenBody): Promise<ApiToken> => {\n const encryptionService = getService('encryption');\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);\n assertValidLifespan(attributes.lifespan);\n\n // Create the token\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').create({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n data: {\n ...omit('permissions', attributes),\n accessKey: hash(accessKey),\n encryptedKey,\n ...getExpirationFields(attributes.lifespan),\n },\n });\n\n const result: ApiToken = { ...apiToken, accessKey };\n\n // If this is a custom type token, create and the related permissions\n if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {\n // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries\n // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({\n // populate: POPULATE_FIELDS,\n // data: attributes.permissions.map(action => ({ action, token: apiToken })),\n // });\n await Promise.all(\n uniq(attributes.permissions).map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: apiToken },\n })\n )\n );\n\n const currentPermissions = await strapi.db\n .query('admin::api-token')\n .load(apiToken, 'permissions');\n\n if (currentPermissions) {\n Object.assign(result, { permissions: map('action', currentPermissions) });\n }\n }\n\n return result;\n};\n\nconst regenerate = async (id: string | number): Promise<ApiToken> => {\n const accessKey = crypto.randomBytes(128).toString('hex');\n const encryptionService = getService('encryption');\n const encryptedKey = encryptionService.encrypt(accessKey);\n\n const apiToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: ['id', 'accessKey'],\n where: { id },\n data: {\n accessKey: hash(accessKey),\n encryptedKey,\n },\n });\n\n if (!apiToken) {\n throw new NotFoundError('The provided token id does not exist');\n }\n\n return {\n ...apiToken,\n accessKey,\n };\n};\n\nconst checkSaltIsDefined = () => {\n if (!strapi.config.get('admin.apiToken.salt')) {\n // TODO V5: stop reading API_TOKEN_SALT\n if (process.env.API_TOKEN_SALT) {\n process.emitWarning(`[deprecated] In future versions, Strapi will stop reading directly from the environment variable API_TOKEN_SALT. Please set apiToken.salt in config/admin.js instead.\nFor security reasons, keep storing the secret in an environment variable and use env() to read it in config/admin.js (ex: \\`apiToken: { salt: env('API_TOKEN_SALT') }\\`). See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);\n\n strapi.config.set('admin.apiToken.salt', process.env.API_TOKEN_SALT);\n } else {\n throw new Error(\n `Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n }\n};\n\n/**\n * Return a list of all tokens and their permissions\n */\nconst list = async (): Promise<Array<ApiToken>> => {\n const tokens: Array<DBApiToken> = await strapi.db.query('admin::api-token').findMany({\n select: SELECT_FIELDS,\n populate: POPULATE_FIELDS,\n orderBy: { name: 'ASC' },\n });\n\n if (!tokens) {\n return tokens;\n }\n\n return tokens.map((token) => flattenTokenPermissions(token));\n};\n\n/**\n * Revoke (delete) a token\n */\nconst revoke = async (id: string | number): Promise<ApiToken> => {\n return strapi.db\n .query('admin::api-token')\n .delete({ select: SELECT_FIELDS, populate: POPULATE_FIELDS, where: { id } });\n};\n\n/**\n * Retrieve a token by id\n */\nconst getById = async (id: string | number) => {\n return getBy({ id });\n};\n\n/**\n * Retrieve a token by name\n */\nconst getByName = async (name: string) => {\n return getBy({ name });\n};\n\n/**\n * Update a token and its permissions\n */\nconst update = async (\n id: string | number,\n attributes: Update.Request['body']\n): Promise<ApiToken> => {\n // retrieve token without permissions\n const originalToken: DBApiToken = await strapi.db\n .query('admin::api-token')\n .findOne({ where: { id } });\n\n if (!originalToken) {\n throw new NotFoundError('Token not found');\n }\n\n const changingTypeToCustom =\n attributes.type === constants.API_TOKEN_TYPE.CUSTOM &&\n originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;\n\n // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid\n // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update\n if (attributes.permissions || changingTypeToCustom) {\n assertCustomTokenPermissionsValidity(\n attributes.type || originalToken.type,\n attributes.permissions || originalToken.permissions\n );\n }\n\n assertValidLifespan(attributes.lifespan);\n\n const updatedToken: ApiToken = await strapi.db.query('admin::api-token').update({\n select: SELECT_FIELDS,\n where: { id },\n data: omit('permissions', attributes),\n });\n\n // custom tokens need to have their permissions updated as well\n if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {\n const currentPermissionsResult = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n const currentPermissions = map('action', currentPermissionsResult || []);\n const newPermissions = uniq(attributes.permissions);\n\n const actionsToDelete = difference(currentPermissions, newPermissions);\n const actionsToAdd = difference(newPermissions, currentPermissions);\n\n // TODO: improve efficiency here\n // method using a loop -- works but very inefficient\n await Promise.all(\n actionsToDelete.map((action) =>\n strapi.db.query('admin::api-token-permission').delete({\n where: { action, token: id },\n })\n )\n );\n\n // TODO: improve efficiency here\n // using a loop -- works but very inefficient\n await Promise.all(\n actionsToAdd.map((action) =>\n strapi.db.query('admin::api-token-permission').create({\n data: { action, token: id },\n })\n )\n );\n }\n // if type is not custom, make sure any old permissions get removed\n else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {\n await strapi.db.query('admin::api-token-permission').delete({\n where: { token: id },\n });\n }\n\n // retrieve permissions\n const permissionsFromDb = await strapi.db\n .query('admin::api-token')\n .load(updatedToken, 'permissions');\n\n return {\n ...updatedToken,\n permissions: permissionsFromDb ? permissionsFromDb.map((p: any) => p.action) : undefined,\n };\n};\n\nconst count = async (where = {}): Promise<number> => {\n return strapi.db.query('admin::api-token').count({ where });\n};\n\nexport {\n create,\n count,\n regenerate,\n exists,\n checkSaltIsDefined,\n hash,\n list,\n revoke,\n getById,\n update,\n getByName,\n getBy,\n};\n"],"names":["ValidationError","NotFoundError","errors","SELECT_FIELDS","POPULATE_FIELDS","assertCustomTokenPermissionsValidity","type","permissions","constants","API_TOKEN_TYPE","CUSTOM","isEmpty","isArray","validPermissions","strapi","contentAPI","providers","action","keys","invalidPermissions","difference","join","isValidLifespan","lifespan","isNil","isNumber","Object","values","API_TOKEN_LIFESPANS","includes","assertValidLifespan","flattenTokenPermissions","token","map","getBy","whereParams","length","db","query","findOne","select","populate","where","encryptedKey","rest","accessKey","getService","decrypt","exists","apiToken","hash","crypto","createHmac","config","get","update","digest","getExpirationFields","isValidNumber","Number","isFinite","expiresAt","Date","now","create","attributes","encryptionService","randomBytes","toString","encrypt","data","omit","result","Promise","all","uniq","currentPermissions","load","assign","regenerate","id","checkSaltIsDefined","process","env","API_TOKEN_SALT","emitWarning","set","Error","list","tokens","findMany","orderBy","name","revoke","delete","getById","getByName","originalToken","changingTypeToCustom","updatedToken","currentPermissionsResult","newPermissions","actionsToDelete","actionsToAdd","permissionsFromDb","p","undefined","count"],"mappings":"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"}
@@ -2,6 +2,7 @@ import crypto from 'crypto';
2
2
  import { omit, uniq, map, difference, isEmpty, isArray, isNumber, isNil } from 'lodash/fp';
3
3
  import { errors } from '@strapi/utils';
4
4
  import constants from './constants.mjs';
5
+ import { getService } from '../utils/index.mjs';
5
6
 
6
7
  const { ValidationError, NotFoundError } = errors;
7
8
  const SELECT_FIELDS = [
@@ -76,14 +77,25 @@ const POPULATE_FIELDS = [
76
77
  return null;
77
78
  }
78
79
  const token = await strapi.db.query('admin::api-token').findOne({
79
- select: SELECT_FIELDS,
80
+ select: [
81
+ ...SELECT_FIELDS,
82
+ 'encryptedKey'
83
+ ],
80
84
  populate: POPULATE_FIELDS,
81
85
  where: whereParams
82
86
  });
83
87
  if (!token) {
84
88
  return token;
85
89
  }
86
- return flattenTokenPermissions(token);
90
+ const { encryptedKey, ...rest } = token;
91
+ if (!encryptedKey) {
92
+ return flattenTokenPermissions(rest);
93
+ }
94
+ const accessKey = getService('encryption').decrypt(encryptedKey);
95
+ return flattenTokenPermissions({
96
+ ...rest,
97
+ accessKey
98
+ });
87
99
  };
88
100
  /**
89
101
  * Check if token exists
@@ -110,7 +122,9 @@ const getExpirationFields = (lifespan)=>{
110
122
  /**
111
123
  * Create a token and its permissions
112
124
  */ const create = async (attributes)=>{
125
+ const encryptionService = getService('encryption');
113
126
  const accessKey = crypto.randomBytes(128).toString('hex');
127
+ const encryptedKey = encryptionService.encrypt(accessKey);
114
128
  assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);
115
129
  assertValidLifespan(attributes.lifespan);
116
130
  // Create the token
@@ -120,6 +134,7 @@ const getExpirationFields = (lifespan)=>{
120
134
  data: {
121
135
  ...omit('permissions', attributes),
122
136
  accessKey: hash(accessKey),
137
+ encryptedKey,
123
138
  ...getExpirationFields(attributes.lifespan)
124
139
  }
125
140
  });
@@ -151,6 +166,8 @@ const getExpirationFields = (lifespan)=>{
151
166
  };
152
167
  const regenerate = async (id)=>{
153
168
  const accessKey = crypto.randomBytes(128).toString('hex');
169
+ const encryptionService = getService('encryption');
170
+ const encryptedKey = encryptionService.encrypt(accessKey);
154
171
  const apiToken = await strapi.db.query('admin::api-token').update({
155
172
  select: [
156
173
  'id',
@@ -160,7 +177,8 @@ const regenerate = async (id)=>{
160
177
  id
161
178
  },
162
179
  data: {
163
- accessKey: hash(accessKey)
180
+ accessKey: hash(accessKey),
181
+ encryptedKey
164
182
  }
165
183
  });
166
184
  if (!apiToken) {