@strapi/admin 5.17.0 → 5.18.1
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.
- package/dist/admin/admin/src/StrapiApp.js +27 -4
- package/dist/admin/admin/src/StrapiApp.js.map +1 -1
- package/dist/admin/admin/src/StrapiApp.mjs +27 -4
- package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Provider.js +2 -1
- package/dist/admin/admin/src/components/GuidedTour/Provider.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Provider.mjs +2 -1
- package/dist/admin/admin/src/components/GuidedTour/Provider.mjs.map +1 -1
- package/dist/admin/admin/src/components/LeftMenu.js +1 -1
- package/dist/admin/admin/src/components/LeftMenu.js.map +1 -1
- package/dist/admin/admin/src/components/LeftMenu.mjs +2 -2
- package/dist/admin/admin/src/components/LeftMenu.mjs.map +1 -1
- package/dist/admin/admin/src/components/MainNav/NavLink.js +40 -4
- package/dist/admin/admin/src/components/MainNav/NavLink.js.map +1 -1
- package/dist/admin/admin/src/components/MainNav/NavLink.mjs +21 -4
- package/dist/admin/admin/src/components/MainNav/NavLink.mjs.map +1 -1
- package/dist/admin/admin/src/components/MainNav/NavUser.js +1 -1
- package/dist/admin/admin/src/components/MainNav/NavUser.js.map +1 -1
- package/dist/admin/admin/src/components/MainNav/NavUser.mjs +1 -1
- package/dist/admin/admin/src/components/MainNav/NavUser.mjs.map +1 -1
- package/dist/admin/admin/src/components/Providers.js +0 -2
- package/dist/admin/admin/src/components/Providers.js.map +1 -1
- package/dist/admin/admin/src/components/Providers.mjs +0 -2
- package/dist/admin/admin/src/components/Providers.mjs.map +1 -1
- package/dist/admin/admin/src/components/SubNav.js +27 -7
- package/dist/admin/admin/src/components/SubNav.js.map +1 -1
- package/dist/admin/admin/src/components/SubNav.mjs +28 -8
- package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.js +31 -9
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.js.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.mjs +31 -9
- package/dist/admin/admin/src/components/UnstableGuidedTour/Context.mjs.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Overview.js +306 -0
- package/dist/admin/admin/src/components/UnstableGuidedTour/Overview.js.map +1 -0
- package/dist/admin/admin/src/components/UnstableGuidedTour/Overview.mjs +304 -0
- package/dist/admin/admin/src/components/UnstableGuidedTour/Overview.mjs.map +1 -0
- package/dist/admin/admin/src/components/UnstableGuidedTour/Step.js +73 -27
- package/dist/admin/admin/src/components/UnstableGuidedTour/Step.js.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Step.mjs +75 -30
- package/dist/admin/admin/src/components/UnstableGuidedTour/Step.mjs.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.js +316 -28
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.js.map +1 -1
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.mjs +319 -30
- package/dist/admin/admin/src/components/UnstableGuidedTour/Tours.mjs.map +1 -1
- package/dist/admin/admin/src/components/Widgets.js +52 -0
- package/dist/admin/admin/src/components/Widgets.js.map +1 -0
- package/dist/admin/admin/src/components/Widgets.mjs +50 -0
- package/dist/admin/admin/src/components/Widgets.mjs.map +1 -0
- package/dist/admin/admin/src/core/apis/Widgets.js.map +1 -1
- package/dist/admin/admin/src/core/apis/Widgets.mjs.map +1 -1
- package/dist/admin/admin/src/features/Auth.js.map +1 -1
- package/dist/admin/admin/src/features/Auth.mjs.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.js +3 -1
- package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.mjs +3 -1
- package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js +93 -0
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs +95 -3
- package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js +8 -3
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs +10 -5
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.js +6 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.mjs +6 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/CollapsableContentType.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js +58 -53
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs +58 -53
- package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +38 -2
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +38 -2
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/es.json.js +3 -1
- package/dist/admin/admin/src/translations/es.json.js.map +1 -1
- package/dist/admin/admin/src/translations/es.json.mjs +3 -1
- package/dist/admin/admin/src/translations/es.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.js +3 -1
- package/dist/admin/admin/src/translations/fr.json.js.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.mjs +3 -1
- package/dist/admin/admin/src/translations/fr.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/users.js +8 -0
- package/dist/admin/admin/src/utils/users.js.map +1 -1
- package/dist/admin/admin/src/utils/users.mjs +8 -1
- package/dist/admin/admin/src/utils/users.mjs.map +1 -1
- package/dist/admin/admin/tests/server.js +8 -0
- package/dist/admin/admin/tests/server.js.map +1 -1
- package/dist/admin/admin/tests/server.mjs +8 -0
- package/dist/admin/admin/tests/server.mjs.map +1 -1
- package/dist/admin/admin/tests/utils.js +25 -21
- package/dist/admin/admin/tests/utils.js.map +1 -1
- package/dist/admin/admin/tests/utils.mjs +25 -21
- package/dist/admin/admin/tests/utils.mjs.map +1 -1
- package/dist/admin/src/components/UnstableGuidedTour/Context.d.ts +12 -3
- package/dist/admin/src/components/UnstableGuidedTour/Overview.d.ts +1 -0
- package/dist/admin/src/components/UnstableGuidedTour/Step.d.ts +11 -3
- package/dist/admin/src/components/UnstableGuidedTour/Tours.d.ts +40 -9
- package/dist/admin/src/components/Widgets.d.ts +2 -0
- package/dist/admin/src/core/apis/Widgets.d.ts +1 -1
- package/dist/admin/src/features/Auth.d.ts +1 -1
- package/dist/admin/src/pages/Settings/components/Tokens/TokenBox.d.ts +1 -0
- package/dist/admin/src/utils/users.d.ts +5 -1
- package/dist/server/server/src/services/guided-tour.js +20 -2
- package/dist/server/server/src/services/guided-tour.js.map +1 -1
- package/dist/server/server/src/services/guided-tour.mjs +20 -2
- package/dist/server/server/src/services/guided-tour.mjs.map +1 -1
- package/dist/server/server/src/strategies/api-token.js +15 -4
- package/dist/server/server/src/strategies/api-token.js.map +1 -1
- package/dist/server/server/src/strategies/api-token.mjs +15 -4
- package/dist/server/server/src/strategies/api-token.mjs.map +1 -1
- package/dist/server/src/services/guided-tour.d.ts.map +1 -1
- package/dist/server/src/strategies/api-token.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -14,6 +14,7 @@ import { createMemoryRouter, RouterProvider } from 'react-router-dom';
|
|
|
14
14
|
import { GuidedTourProvider } from '../src/components/GuidedTour/Provider.mjs';
|
|
15
15
|
import { LanguageProvider } from '../src/components/LanguageProvider.mjs';
|
|
16
16
|
import { Theme } from '../src/components/Theme.mjs';
|
|
17
|
+
import { UnstableGuidedTourContext } from '../src/components/UnstableGuidedTour/Context.mjs';
|
|
17
18
|
import { RBAC } from '../src/core/apis/rbac.mjs';
|
|
18
19
|
import { AppInfoProvider } from '../src/features/AppInfo.mjs';
|
|
19
20
|
import { AuthProvider } from '../src/features/Auth.mjs';
|
|
@@ -135,28 +136,31 @@ const Providers = ({ children, initialEntries, storeConfig, permissions = [] })=
|
|
|
135
136
|
},
|
|
136
137
|
children: /*#__PURE__*/ jsx(NotificationsProvider, {
|
|
137
138
|
children: /*#__PURE__*/ jsx(GuidedTourProvider, {
|
|
138
|
-
children: /*#__PURE__*/ jsx(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
children: /*#__PURE__*/ jsx(UnstableGuidedTourContext, {
|
|
140
|
+
enabled: false,
|
|
141
|
+
children: /*#__PURE__*/ jsx(ConfigurationContextProvider, {
|
|
142
|
+
showReleaseNotification: false,
|
|
143
|
+
logos: {
|
|
144
|
+
auth: {
|
|
145
|
+
default: 'default'
|
|
146
|
+
},
|
|
147
|
+
menu: {
|
|
148
|
+
default: 'default'
|
|
149
|
+
}
|
|
143
150
|
},
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
communityEdition: true,
|
|
158
|
-
shouldUpdateStrapi: false,
|
|
159
|
-
children: children
|
|
151
|
+
updateProjectSettings: jest.fn(),
|
|
152
|
+
children: /*#__PURE__*/ jsx(AppInfoProvider, {
|
|
153
|
+
autoReload: true,
|
|
154
|
+
useYarn: true,
|
|
155
|
+
dependencies: {
|
|
156
|
+
'@strapi/plugin-documentation': '4.2.0',
|
|
157
|
+
'@strapi/provider-upload-cloudinary': '4.2.0'
|
|
158
|
+
},
|
|
159
|
+
strapiVersion: "4.1.0",
|
|
160
|
+
communityEdition: true,
|
|
161
|
+
shouldUpdateStrapi: false,
|
|
162
|
+
children: children
|
|
163
|
+
})
|
|
160
164
|
})
|
|
161
165
|
})
|
|
162
166
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../../../../admin/tests/utils.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport * as React from 'react';\n\nimport { ConfigureStoreOptions, configureStore } from '@reduxjs/toolkit';\nimport { fixtures } from '@strapi/admin-test-utils';\nimport { darkTheme, lightTheme } from '@strapi/design-system';\nimport {\n fireEvent,\n renderHook as renderHookRTL,\n render as renderRTL,\n waitFor,\n RenderOptions as RTLRenderOptions,\n RenderResult,\n act,\n screen,\n RenderHookOptions,\n RenderHookResult,\n Queries,\n} from '@testing-library/react';\nimport { userEvent } from '@testing-library/user-event';\nimport { DndProvider } from 'react-dnd';\nimport { HTML5Backend } from 'react-dnd-html5-backend';\nimport { QueryClient, QueryClientProvider, setLogger } from 'react-query';\nimport { Provider } from 'react-redux';\nimport { MemoryRouterProps, RouterProvider, createMemoryRouter } from 'react-router-dom';\n\nimport { GuidedTourProvider } from '../src/components/GuidedTour/Provider';\nimport { LanguageProvider } from '../src/components/LanguageProvider';\nimport { Theme } from '../src/components/Theme';\nimport { RBAC } from '../src/core/apis/rbac';\nimport { AppInfoProvider } from '../src/features/AppInfo';\nimport { AuthProvider, type Permission } from '../src/features/Auth';\nimport { _internalConfigurationContextProvider as ConfigurationContextProvider } from '../src/features/Configuration';\nimport { NotificationsProvider } from '../src/features/Notifications';\nimport { StrapiAppProvider } from '../src/features/StrapiApp';\nimport { reducer as appReducer } from '../src/reducer';\nimport { adminApi } from '../src/services/api';\n\nimport { server } from './server';\nimport { initialState } from './store';\n\nsetLogger({\n log: () => {},\n warn: () => {},\n error: () => {},\n});\n\ninterface ProvidersProps {\n children: React.ReactNode;\n initialEntries?: MemoryRouterProps['initialEntries'];\n storeConfig?: Partial<ConfigureStoreOptions>;\n permissions?: Permission[] | ((defaultPermissions: Permission[]) => Permission[] | undefined);\n}\n\nconst defaultTestStoreConfig = () => ({\n preloadedState: initialState(),\n reducer: {\n [adminApi.reducerPath]: adminApi.reducer,\n admin_app: appReducer,\n },\n // @ts-expect-error – this fails.\n middleware: (getDefaultMiddleware) => [\n ...getDefaultMiddleware({\n // Disable timing checks for test env\n immutableCheck: false,\n serializableCheck: false,\n }),\n adminApi.middleware,\n ],\n});\n\nconst DEFAULT_PERMISSIONS = [\n ...fixtures.permissions.allPermissions,\n {\n id: 314,\n action: 'admin::users.read',\n subject: null,\n properties: {},\n conditions: [],\n actionParameters: {},\n },\n];\n\nconst Providers = ({ children, initialEntries, storeConfig, permissions = [] }: ProvidersProps) => {\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n },\n },\n });\n\n const store = configureStore({\n ...defaultTestStoreConfig(),\n ...storeConfig,\n });\n\n const allPermissions =\n typeof permissions === 'function'\n ? permissions(DEFAULT_PERMISSIONS)\n : [...DEFAULT_PERMISSIONS, ...permissions];\n\n const router = createMemoryRouter(\n [\n {\n path: '/*',\n element: (\n <StrapiAppProvider\n components={{}}\n rbac={new RBAC()}\n widgets={{\n widgets: {},\n getAll: jest.fn(),\n register: jest.fn(),\n }}\n customFields={{\n customFields: {},\n get: jest.fn().mockReturnValue({\n name: 'color',\n pluginId: 'mycustomfields',\n type: 'text',\n icon: jest.fn(),\n intlLabel: {\n id: 'mycustomfields.color.label',\n defaultMessage: 'Color',\n },\n intlDescription: {\n id: 'mycustomfields.color.description',\n defaultMessage: 'Select any color',\n },\n components: {\n Input: jest.fn().mockResolvedValue({ default: jest.fn() }),\n },\n }),\n getAll: jest.fn(),\n register: jest.fn(),\n }}\n fields={{}}\n menu={[]}\n getAdminInjectedComponents={jest.fn()}\n getPlugin={jest.fn()}\n plugins={{}}\n runHookParallel={jest.fn()}\n runHookWaterfall={jest.fn().mockImplementation((_name, initialValue) => initialValue)}\n runHookSeries={jest.fn()}\n settings={{}}\n >\n <Provider store={store}>\n <AuthProvider _defaultPermissions={allPermissions} _disableRenewToken={true}>\n <QueryClientProvider client={queryClient}>\n <DndProvider backend={HTML5Backend}>\n <LanguageProvider messages={{}}>\n <Theme\n themes={{\n dark: darkTheme,\n light: lightTheme,\n }}\n >\n <NotificationsProvider>\n <GuidedTourProvider>\n <ConfigurationContextProvider\n showReleaseNotification={false}\n logos={{\n auth: { default: 'default' },\n menu: { default: 'default' },\n }}\n updateProjectSettings={jest.fn()}\n >\n <AppInfoProvider\n autoReload\n useYarn\n dependencies={{\n '@strapi/plugin-documentation': '4.2.0',\n '@strapi/provider-upload-cloudinary': '4.2.0',\n }}\n strapiVersion=\"4.1.0\"\n communityEdition\n shouldUpdateStrapi={false}\n >\n {children}\n </AppInfoProvider>\n </ConfigurationContextProvider>\n </GuidedTourProvider>\n </NotificationsProvider>\n </Theme>\n </LanguageProvider>\n </DndProvider>\n </QueryClientProvider>\n </AuthProvider>\n </Provider>\n </StrapiAppProvider>\n ),\n },\n ],\n {\n initialEntries,\n }\n );\n\n // en is the default locale of the admin app.\n return <RouterProvider router={router} />;\n};\n\n// eslint-disable-next-line react/jsx-no-useless-fragment\nconst fallbackWrapper = ({ children }: { children: React.ReactNode }) => <>{children}</>;\n\nexport interface RenderOptions {\n renderOptions?: RTLRenderOptions;\n userEventOptions?: Parameters<typeof userEvent.setup>[0];\n initialEntries?: MemoryRouterProps['initialEntries'];\n providerOptions?: Pick<ProvidersProps, 'storeConfig' | 'permissions'>;\n}\n\n/**\n * @alpha\n * @description A custom render function that wraps the component with the necessary providers,\n * for use of testing components within the Strapi Admin.\n */\nconst render = (\n ui: React.ReactElement,\n { renderOptions, userEventOptions, initialEntries, providerOptions }: RenderOptions = {}\n): RenderResult & { user: ReturnType<typeof userEvent.setup> } => {\n const { wrapper: Wrapper = fallbackWrapper, ...restOptions } = renderOptions ?? {};\n\n return {\n ...renderRTL(ui, {\n wrapper: ({ children }) => (\n <Providers initialEntries={initialEntries} {...providerOptions}>\n <Wrapper>{children}</Wrapper>\n </Providers>\n ),\n ...restOptions,\n }),\n user: userEvent.setup({\n skipHover: true,\n ...userEventOptions,\n }),\n };\n};\n\n/**\n * @alpha\n * @description A custom render-hook function that wraps the component with the necessary providers,\n * for use of testing hooks within the Strapi Admin.\n */\nconst renderHook = <\n Result,\n Props,\n Q extends Queries,\n Container extends Element | DocumentFragment = HTMLElement,\n BaseElement extends Element | DocumentFragment = Container,\n>(\n hook: (initialProps: Props) => Result,\n options?: RenderHookOptions<Props, Q, Container, BaseElement> &\n Pick<RenderOptions, 'initialEntries' | 'providerOptions'>\n): RenderHookResult<Result, Props> => {\n const {\n wrapper: Wrapper = fallbackWrapper,\n initialEntries,\n providerOptions,\n ...restOptions\n } = options ?? {};\n\n return renderHookRTL(hook, {\n wrapper: ({ children }) => (\n <Providers initialEntries={initialEntries} {...providerOptions}>\n <Wrapper>{children}</Wrapper>\n </Providers>\n ),\n ...restOptions,\n });\n};\n\nexport { render, renderHook, waitFor, server, act, screen, fireEvent, defaultTestStoreConfig };\n"],"names":["setLogger","log","warn","error","defaultTestStoreConfig","preloadedState","initialState","reducer","adminApi","reducerPath","admin_app","appReducer","middleware","getDefaultMiddleware","immutableCheck","serializableCheck","DEFAULT_PERMISSIONS","fixtures","permissions","allPermissions","id","action","subject","properties","conditions","actionParameters","Providers","children","initialEntries","storeConfig","queryClient","QueryClient","defaultOptions","queries","retry","store","configureStore","router","createMemoryRouter","path","element","_jsx","StrapiAppProvider","components","rbac","RBAC","widgets","getAll","jest","fn","register","customFields","get","mockReturnValue","name","pluginId","type","icon","intlLabel","defaultMessage","intlDescription","Input","mockResolvedValue","default","fields","menu","getAdminInjectedComponents","getPlugin","plugins","runHookParallel","runHookWaterfall","mockImplementation","_name","initialValue","runHookSeries","settings","Provider","AuthProvider","_defaultPermissions","_disableRenewToken","QueryClientProvider","client","DndProvider","backend","HTML5Backend","LanguageProvider","messages","Theme","themes","dark","darkTheme","light","lightTheme","NotificationsProvider","GuidedTourProvider","ConfigurationContextProvider","showReleaseNotification","logos","auth","updateProjectSettings","AppInfoProvider","autoReload","useYarn","dependencies","strapiVersion","communityEdition","shouldUpdateStrapi","RouterProvider","fallbackWrapper","_Fragment","render","ui","renderOptions","userEventOptions","providerOptions","wrapper","Wrapper","restOptions","renderRTL","user","userEvent","setup","skipHover","renderHook","hook","options","renderHookRTL"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCAA,SAAU,CAAA;AACRC,IAAAA,GAAAA,EAAK,IAAO,EAAA;AACZC,IAAAA,IAAAA,EAAM,IAAO,EAAA;AACbC,IAAAA,KAAAA,EAAO,IAAO;AAChB,CAAA,CAAA;AASMC,MAAAA,sBAAAA,GAAyB,KAAO;QACpCC,cAAgBC,EAAAA,YAAAA,EAAAA;QAChBC,OAAS,EAAA;AACP,YAAA,CAACC,QAASC,CAAAA,WAAW,GAAGD,SAASD,OAAO;YACxCG,SAAWC,EAAAA;AACb,SAAA;;AAEAC,QAAAA,UAAAA,EAAY,CAACC,oBAAyB,GAAA;mBACjCA,oBAAqB,CAAA;;oBAEtBC,cAAgB,EAAA,KAAA;oBAChBC,iBAAmB,EAAA;AACrB,iBAAA,CAAA;AACAP,gBAAAA,QAAAA,CAASI;AACV;KACH;AAEA,MAAMI,mBAAsB,GAAA;OACvBC,QAASC,CAAAA,WAAW,CAACC,cAAc;AACtC,IAAA;QACEC,EAAI,EAAA,GAAA;QACJC,MAAQ,EAAA,mBAAA;QACRC,OAAS,EAAA,IAAA;AACTC,QAAAA,UAAAA,EAAY,EAAC;AACbC,QAAAA,UAAAA,EAAY,EAAE;AACdC,QAAAA,gBAAAA,EAAkB;AACpB;AACD,CAAA;AAED,MAAMC,SAAAA,GAAY,CAAC,EAAEC,QAAQ,EAAEC,cAAc,EAAEC,WAAW,EAAEX,WAAc,GAAA,EAAE,EAAkB,GAAA;IAC5F,MAAMY,WAAAA,GAAc,IAAIC,WAAY,CAAA;QAClCC,cAAgB,EAAA;YACdC,OAAS,EAAA;gBACPC,KAAO,EAAA;AACT;AACF;AACF,KAAA,CAAA;AAEA,IAAA,MAAMC,QAAQC,cAAe,CAAA;AAC3B,QAAA,GAAGhC,sBAAwB,EAAA;AAC3B,QAAA,GAAGyB;AACL,KAAA,CAAA;AAEA,IAAA,MAAMV,cACJ,GAAA,OAAOD,WAAgB,KAAA,UAAA,GACnBA,YAAYF,mBACZ,CAAA,GAAA;AAAIA,QAAAA,GAAAA,mBAAAA;AAAwBE,QAAAA,GAAAA;AAAY,KAAA;AAE9C,IAAA,MAAMmB,SAASC,kBACb,CAAA;AACE,QAAA;YACEC,IAAM,EAAA,IAAA;AACNC,YAAAA,OAAAA,gBACEC,GAACC,CAAAA,iBAAAA,EAAAA;AACCC,gBAAAA,UAAAA,EAAY,EAAC;AACbC,gBAAAA,IAAAA,EAAM,IAAIC,IAAAA,EAAAA;gBACVC,OAAS,EAAA;AACPA,oBAAAA,OAAAA,EAAS,EAAC;AACVC,oBAAAA,MAAAA,EAAQC,KAAKC,EAAE,EAAA;AACfC,oBAAAA,QAAAA,EAAUF,KAAKC,EAAE;AACnB,iBAAA;gBACAE,YAAc,EAAA;AACZA,oBAAAA,YAAAA,EAAc,EAAC;AACfC,oBAAAA,GAAAA,EAAKJ,IAAKC,CAAAA,EAAE,EAAGI,CAAAA,eAAe,CAAC;wBAC7BC,IAAM,EAAA,OAAA;wBACNC,QAAU,EAAA,gBAAA;wBACVC,IAAM,EAAA,MAAA;AACNC,wBAAAA,IAAAA,EAAMT,KAAKC,EAAE,EAAA;wBACbS,SAAW,EAAA;4BACTtC,EAAI,EAAA,4BAAA;4BACJuC,cAAgB,EAAA;AAClB,yBAAA;wBACAC,eAAiB,EAAA;4BACfxC,EAAI,EAAA,kCAAA;4BACJuC,cAAgB,EAAA;AAClB,yBAAA;wBACAhB,UAAY,EAAA;AACVkB,4BAAAA,KAAAA,EAAOb,IAAKC,CAAAA,EAAE,EAAGa,CAAAA,iBAAiB,CAAC;AAAEC,gCAAAA,OAAAA,EAASf,KAAKC,EAAE;AAAG,6BAAA;AAC1D;AACF,qBAAA,CAAA;AACAF,oBAAAA,MAAAA,EAAQC,KAAKC,EAAE,EAAA;AACfC,oBAAAA,QAAAA,EAAUF,KAAKC,EAAE;AACnB,iBAAA;AACAe,gBAAAA,MAAAA,EAAQ,EAAC;AACTC,gBAAAA,IAAAA,EAAM,EAAE;AACRC,gBAAAA,0BAAAA,EAA4BlB,KAAKC,EAAE,EAAA;AACnCkB,gBAAAA,SAAAA,EAAWnB,KAAKC,EAAE,EAAA;AAClBmB,gBAAAA,OAAAA,EAAS,EAAC;AACVC,gBAAAA,eAAAA,EAAiBrB,KAAKC,EAAE,EAAA;AACxBqB,gBAAAA,gBAAAA,EAAkBtB,KAAKC,EAAE,EAAA,CAAGsB,kBAAkB,CAAC,CAACC,OAAOC,YAAiBA,GAAAA,YAAAA,CAAAA;AACxEC,gBAAAA,aAAAA,EAAe1B,KAAKC,EAAE,EAAA;AACtB0B,gBAAAA,QAAAA,EAAU,EAAC;AAEX,gBAAA,QAAA,gBAAAlC,GAACmC,CAAAA,QAAAA,EAAAA;oBAASzC,KAAOA,EAAAA,KAAAA;AACf,oBAAA,QAAA,gBAAAM,GAACoC,CAAAA,YAAAA,EAAAA;wBAAaC,mBAAqB3D,EAAAA,cAAAA;wBAAgB4D,kBAAoB,EAAA,IAAA;AACrE,wBAAA,QAAA,gBAAAtC,GAACuC,CAAAA,mBAAAA,EAAAA;4BAAoBC,MAAQnD,EAAAA,WAAAA;AAC3B,4BAAA,QAAA,gBAAAW,GAACyC,CAAAA,WAAAA,EAAAA;gCAAYC,OAASC,EAAAA,YAAAA;AACpB,gCAAA,QAAA,gBAAA3C,GAAC4C,CAAAA,gBAAAA,EAAAA;AAAiBC,oCAAAA,QAAAA,EAAU,EAAC;AAC3B,oCAAA,QAAA,gBAAA7C,GAAC8C,CAAAA,KAAAA,EAAAA;wCACCC,MAAQ,EAAA;4CACNC,IAAMC,EAAAA,SAAAA;4CACNC,KAAOC,EAAAA;AACT,yCAAA;AAEA,wCAAA,QAAA,gBAAAnD,GAACoD,CAAAA,qBAAAA,EAAAA;AACC,4CAAA,QAAA,gBAAApD,GAACqD,CAAAA,kBAAAA,EAAAA;AACC,gDAAA,QAAA,gBAAArD,GAACsD,CAAAA,4BAAAA,EAAAA;oDACCC,uBAAyB,EAAA,KAAA;oDACzBC,KAAO,EAAA;wDACLC,IAAM,EAAA;4DAAEnC,OAAS,EAAA;AAAU,yDAAA;wDAC3BE,IAAM,EAAA;4DAAEF,OAAS,EAAA;AAAU;AAC7B,qDAAA;AACAoC,oDAAAA,qBAAAA,EAAuBnD,KAAKC,EAAE,EAAA;AAE9B,oDAAA,QAAA,gBAAAR,GAAC2D,CAAAA,eAAAA,EAAAA;wDACCC,UAAU,EAAA,IAAA;wDACVC,OAAO,EAAA,IAAA;wDACPC,YAAc,EAAA;4DACZ,8BAAgC,EAAA,OAAA;4DAChC,oCAAsC,EAAA;AACxC,yDAAA;wDACAC,aAAc,EAAA,OAAA;wDACdC,gBAAgB,EAAA,IAAA;wDAChBC,kBAAoB,EAAA,KAAA;AAEnB/E,wDAAAA,QAAAA,EAAAA;;;;;;;;;;;;AAa3B;KACD,EACD;AACEC,QAAAA;AACF,KAAA,CAAA;;AAIF,IAAA,qBAAOa,GAACkE,CAAAA,cAAAA,EAAAA;QAAetE,MAAQA,EAAAA;;AACjC,CAAA;AAEA;AACA,MAAMuE,eAAkB,GAAA,CAAC,EAAEjF,QAAQ,EAAiC,iBAAKc,GAAA,CAAAoE,QAAA,EAAA;AAAGlF,QAAAA,QAAAA,EAAAA;;AAS5E;;;;AAIC,IACKmF,MAAAA,MAAAA,GAAS,CACbC,EAAAA,EACA,EAAEC,aAAa,EAAEC,gBAAgB,EAAErF,cAAc,EAAEsF,eAAe,EAAiB,GAAG,EAAE,GAAA;IAExF,MAAM,EAAEC,SAASC,OAAUR,GAAAA,eAAe,EAAE,GAAGS,WAAAA,EAAa,GAAGL,aAAAA,IAAiB,EAAC;IAEjF,OAAO;AACL,QAAA,GAAGM,SAAUP,EAAI,EAAA;AACfI,YAAAA,OAAAA,EAAS,CAAC,EAAExF,QAAQ,EAAE,iBACpBc,GAACf,CAAAA,SAAAA,EAAAA;oBAAUE,cAAgBA,EAAAA,cAAAA;AAAiB,oBAAA,GAAGsF,eAAe;AAC5D,oBAAA,QAAA,gBAAAzE,GAAC2E,CAAAA,OAAAA,EAAAA;AAASzF,wBAAAA,QAAAA,EAAAA;;;AAGd,YAAA,GAAG0F;SACH,CAAA;QACFE,IAAMC,EAAAA,SAAAA,CAAUC,KAAK,CAAC;YACpBC,SAAW,EAAA,IAAA;AACX,YAAA,GAAGT;AACL,SAAA;AACF,KAAA;AACF;AAEA;;;;IAKA,MAAMU,UAAa,GAAA,CAOjBC,IACAC,EAAAA,OAAAA,GAAAA;AAGA,IAAA,MAAM,EACJV,OAAAA,EAASC,OAAUR,GAAAA,eAAe,EAClChF,cAAc,EACdsF,eAAe,EACf,GAAGG,WACJ,EAAA,GAAGQ,WAAW,EAAC;AAEhB,IAAA,OAAOC,aAAcF,IAAM,EAAA;AACzBT,QAAAA,OAAAA,EAAS,CAAC,EAAExF,QAAQ,EAAE,iBACpBc,GAACf,CAAAA,SAAAA,EAAAA;gBAAUE,cAAgBA,EAAAA,cAAAA;AAAiB,gBAAA,GAAGsF,eAAe;AAC5D,gBAAA,QAAA,gBAAAzE,GAAC2E,CAAAA,OAAAA,EAAAA;AAASzF,oBAAAA,QAAAA,EAAAA;;;AAGd,QAAA,GAAG0F;AACL,KAAA,CAAA;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../../../../admin/tests/utils.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\n\nimport * as React from 'react';\n\nimport { ConfigureStoreOptions, configureStore } from '@reduxjs/toolkit';\nimport { fixtures } from '@strapi/admin-test-utils';\nimport { darkTheme, lightTheme } from '@strapi/design-system';\nimport {\n fireEvent,\n renderHook as renderHookRTL,\n render as renderRTL,\n waitFor,\n RenderOptions as RTLRenderOptions,\n RenderResult,\n act,\n screen,\n RenderHookOptions,\n RenderHookResult,\n Queries,\n} from '@testing-library/react';\nimport { userEvent } from '@testing-library/user-event';\nimport { DndProvider } from 'react-dnd';\nimport { HTML5Backend } from 'react-dnd-html5-backend';\nimport { QueryClient, QueryClientProvider, setLogger } from 'react-query';\nimport { Provider } from 'react-redux';\nimport { MemoryRouterProps, RouterProvider, createMemoryRouter } from 'react-router-dom';\n\nimport { GuidedTourProvider } from '../src/components/GuidedTour/Provider';\nimport { LanguageProvider } from '../src/components/LanguageProvider';\nimport { Theme } from '../src/components/Theme';\nimport { UnstableGuidedTourContext } from '../src/components/UnstableGuidedTour/Context';\nimport { RBAC } from '../src/core/apis/rbac';\nimport { AppInfoProvider } from '../src/features/AppInfo';\nimport { AuthProvider, type Permission } from '../src/features/Auth';\nimport { _internalConfigurationContextProvider as ConfigurationContextProvider } from '../src/features/Configuration';\nimport { NotificationsProvider } from '../src/features/Notifications';\nimport { StrapiAppProvider } from '../src/features/StrapiApp';\nimport { reducer as appReducer } from '../src/reducer';\nimport { adminApi } from '../src/services/api';\n\nimport { server } from './server';\nimport { initialState } from './store';\n\nsetLogger({\n log: () => {},\n warn: () => {},\n error: () => {},\n});\n\ninterface ProvidersProps {\n children: React.ReactNode;\n initialEntries?: MemoryRouterProps['initialEntries'];\n storeConfig?: Partial<ConfigureStoreOptions>;\n permissions?: Permission[] | ((defaultPermissions: Permission[]) => Permission[] | undefined);\n}\n\nconst defaultTestStoreConfig = () => ({\n preloadedState: initialState(),\n reducer: {\n [adminApi.reducerPath]: adminApi.reducer,\n admin_app: appReducer,\n },\n // @ts-expect-error – this fails.\n middleware: (getDefaultMiddleware) => [\n ...getDefaultMiddleware({\n // Disable timing checks for test env\n immutableCheck: false,\n serializableCheck: false,\n }),\n adminApi.middleware,\n ],\n});\n\nconst DEFAULT_PERMISSIONS = [\n ...fixtures.permissions.allPermissions,\n {\n id: 314,\n action: 'admin::users.read',\n subject: null,\n properties: {},\n conditions: [],\n actionParameters: {},\n },\n];\n\nconst Providers = ({ children, initialEntries, storeConfig, permissions = [] }: ProvidersProps) => {\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n },\n },\n });\n\n const store = configureStore({\n ...defaultTestStoreConfig(),\n ...storeConfig,\n });\n\n const allPermissions =\n typeof permissions === 'function'\n ? permissions(DEFAULT_PERMISSIONS)\n : [...DEFAULT_PERMISSIONS, ...permissions];\n\n const router = createMemoryRouter(\n [\n {\n path: '/*',\n element: (\n <StrapiAppProvider\n components={{}}\n rbac={new RBAC()}\n widgets={{\n widgets: {},\n getAll: jest.fn(),\n register: jest.fn(),\n }}\n customFields={{\n customFields: {},\n get: jest.fn().mockReturnValue({\n name: 'color',\n pluginId: 'mycustomfields',\n type: 'text',\n icon: jest.fn(),\n intlLabel: {\n id: 'mycustomfields.color.label',\n defaultMessage: 'Color',\n },\n intlDescription: {\n id: 'mycustomfields.color.description',\n defaultMessage: 'Select any color',\n },\n components: {\n Input: jest.fn().mockResolvedValue({ default: jest.fn() }),\n },\n }),\n getAll: jest.fn(),\n register: jest.fn(),\n }}\n fields={{}}\n menu={[]}\n getAdminInjectedComponents={jest.fn()}\n getPlugin={jest.fn()}\n plugins={{}}\n runHookParallel={jest.fn()}\n runHookWaterfall={jest.fn().mockImplementation((_name, initialValue) => initialValue)}\n runHookSeries={jest.fn()}\n settings={{}}\n >\n <Provider store={store}>\n <AuthProvider _defaultPermissions={allPermissions} _disableRenewToken={true}>\n <QueryClientProvider client={queryClient}>\n <DndProvider backend={HTML5Backend}>\n <LanguageProvider messages={{}}>\n <Theme\n themes={{\n dark: darkTheme,\n light: lightTheme,\n }}\n >\n <NotificationsProvider>\n <GuidedTourProvider>\n <UnstableGuidedTourContext enabled={false}>\n <ConfigurationContextProvider\n showReleaseNotification={false}\n logos={{\n auth: { default: 'default' },\n menu: { default: 'default' },\n }}\n updateProjectSettings={jest.fn()}\n >\n <AppInfoProvider\n autoReload\n useYarn\n dependencies={{\n '@strapi/plugin-documentation': '4.2.0',\n '@strapi/provider-upload-cloudinary': '4.2.0',\n }}\n strapiVersion=\"4.1.0\"\n communityEdition\n shouldUpdateStrapi={false}\n >\n {children}\n </AppInfoProvider>\n </ConfigurationContextProvider>\n </UnstableGuidedTourContext>\n </GuidedTourProvider>\n </NotificationsProvider>\n </Theme>\n </LanguageProvider>\n </DndProvider>\n </QueryClientProvider>\n </AuthProvider>\n </Provider>\n </StrapiAppProvider>\n ),\n },\n ],\n {\n initialEntries,\n }\n );\n\n // en is the default locale of the admin app.\n return <RouterProvider router={router} />;\n};\n\n// eslint-disable-next-line react/jsx-no-useless-fragment\nconst fallbackWrapper = ({ children }: { children: React.ReactNode }) => <>{children}</>;\n\nexport interface RenderOptions {\n renderOptions?: RTLRenderOptions;\n userEventOptions?: Parameters<typeof userEvent.setup>[0];\n initialEntries?: MemoryRouterProps['initialEntries'];\n providerOptions?: Pick<ProvidersProps, 'storeConfig' | 'permissions'>;\n}\n\n/**\n * @alpha\n * @description A custom render function that wraps the component with the necessary providers,\n * for use of testing components within the Strapi Admin.\n */\nconst render = (\n ui: React.ReactElement,\n { renderOptions, userEventOptions, initialEntries, providerOptions }: RenderOptions = {}\n): RenderResult & { user: ReturnType<typeof userEvent.setup> } => {\n const { wrapper: Wrapper = fallbackWrapper, ...restOptions } = renderOptions ?? {};\n\n return {\n ...renderRTL(ui, {\n wrapper: ({ children }) => (\n <Providers initialEntries={initialEntries} {...providerOptions}>\n <Wrapper>{children}</Wrapper>\n </Providers>\n ),\n ...restOptions,\n }),\n user: userEvent.setup({\n skipHover: true,\n ...userEventOptions,\n }),\n };\n};\n\n/**\n * @alpha\n * @description A custom render-hook function that wraps the component with the necessary providers,\n * for use of testing hooks within the Strapi Admin.\n */\nconst renderHook = <\n Result,\n Props,\n Q extends Queries,\n Container extends Element | DocumentFragment = HTMLElement,\n BaseElement extends Element | DocumentFragment = Container,\n>(\n hook: (initialProps: Props) => Result,\n options?: RenderHookOptions<Props, Q, Container, BaseElement> &\n Pick<RenderOptions, 'initialEntries' | 'providerOptions'>\n): RenderHookResult<Result, Props> => {\n const {\n wrapper: Wrapper = fallbackWrapper,\n initialEntries,\n providerOptions,\n ...restOptions\n } = options ?? {};\n\n return renderHookRTL(hook, {\n wrapper: ({ children }) => (\n <Providers initialEntries={initialEntries} {...providerOptions}>\n <Wrapper>{children}</Wrapper>\n </Providers>\n ),\n ...restOptions,\n });\n};\n\nexport { render, renderHook, waitFor, server, act, screen, fireEvent, defaultTestStoreConfig };\n"],"names":["setLogger","log","warn","error","defaultTestStoreConfig","preloadedState","initialState","reducer","adminApi","reducerPath","admin_app","appReducer","middleware","getDefaultMiddleware","immutableCheck","serializableCheck","DEFAULT_PERMISSIONS","fixtures","permissions","allPermissions","id","action","subject","properties","conditions","actionParameters","Providers","children","initialEntries","storeConfig","queryClient","QueryClient","defaultOptions","queries","retry","store","configureStore","router","createMemoryRouter","path","element","_jsx","StrapiAppProvider","components","rbac","RBAC","widgets","getAll","jest","fn","register","customFields","get","mockReturnValue","name","pluginId","type","icon","intlLabel","defaultMessage","intlDescription","Input","mockResolvedValue","default","fields","menu","getAdminInjectedComponents","getPlugin","plugins","runHookParallel","runHookWaterfall","mockImplementation","_name","initialValue","runHookSeries","settings","Provider","AuthProvider","_defaultPermissions","_disableRenewToken","QueryClientProvider","client","DndProvider","backend","HTML5Backend","LanguageProvider","messages","Theme","themes","dark","darkTheme","light","lightTheme","NotificationsProvider","GuidedTourProvider","UnstableGuidedTourContext","enabled","ConfigurationContextProvider","showReleaseNotification","logos","auth","updateProjectSettings","AppInfoProvider","autoReload","useYarn","dependencies","strapiVersion","communityEdition","shouldUpdateStrapi","RouterProvider","fallbackWrapper","_Fragment","render","ui","renderOptions","userEventOptions","providerOptions","wrapper","Wrapper","restOptions","renderRTL","user","userEvent","setup","skipHover","renderHook","hook","options","renderHookRTL"],"mappings":"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"}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import { GetGuidedTourMeta } from '../../../../shared/contracts/admin';
|
|
3
|
+
import { type Tours } from './Tours';
|
|
3
4
|
type ValidTourName = keyof Tours;
|
|
5
|
+
export type ExtendedCompletedActions = (GetGuidedTourMeta.Response['data']['completedActions'][number] | 'didCopyApiToken')[];
|
|
4
6
|
type Action = {
|
|
5
7
|
type: 'next_step';
|
|
6
8
|
payload: ValidTourName;
|
|
7
9
|
} | {
|
|
8
10
|
type: 'skip_tour';
|
|
9
11
|
payload: ValidTourName;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'set_completed_actions';
|
|
14
|
+
payload: ExtendedCompletedActions;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'skip_all_tours';
|
|
10
17
|
};
|
|
11
18
|
type Tour = Record<ValidTourName, {
|
|
12
19
|
currentStep: number;
|
|
@@ -15,15 +22,17 @@ type Tour = Record<ValidTourName, {
|
|
|
15
22
|
}>;
|
|
16
23
|
type State = {
|
|
17
24
|
tours: Tour;
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
completedActions: ExtendedCompletedActions;
|
|
18
27
|
};
|
|
19
28
|
declare const unstableUseGuidedTour: <Selected, ShouldThrow extends boolean = true>(consumerName: string, selector: (value: {
|
|
20
29
|
state: State;
|
|
21
30
|
dispatch: React.Dispatch<Action>;
|
|
22
31
|
}) => Selected, shouldThrowOnMissingContext?: ShouldThrow | undefined) => ShouldThrow extends true ? Selected : Selected | undefined;
|
|
23
32
|
declare function reducer(state: State, action: Action): State;
|
|
24
|
-
declare const UnstableGuidedTourContext: ({ children,
|
|
33
|
+
declare const UnstableGuidedTourContext: ({ children, enabled, }: {
|
|
25
34
|
children: React.ReactNode;
|
|
26
|
-
|
|
35
|
+
enabled?: boolean;
|
|
27
36
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
28
37
|
export type { Action, State, ValidTourName };
|
|
29
38
|
export { UnstableGuidedTourContext, unstableUseGuidedTour, reducer };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const UnstableGuidedTourOverview: () => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { Popover } from '@strapi/design-system';
|
|
2
|
+
import { Popover, FlexProps } from '@strapi/design-system';
|
|
3
3
|
import { type MessageDescriptor } from 'react-intl';
|
|
4
4
|
import { ValidTourName } from './Context';
|
|
5
5
|
type WithChildren = {
|
|
@@ -11,6 +11,7 @@ type WithIntl = {
|
|
|
11
11
|
children?: undefined;
|
|
12
12
|
id: MessageDescriptor['id'];
|
|
13
13
|
defaultMessage: MessageDescriptor['defaultMessage'];
|
|
14
|
+
withArrow?: boolean;
|
|
14
15
|
};
|
|
15
16
|
type WithActionsChildren = {
|
|
16
17
|
children: React.ReactNode;
|
|
@@ -25,11 +26,18 @@ type WithActionsProps = {
|
|
|
25
26
|
type StepProps = WithChildren | WithIntl;
|
|
26
27
|
type ActionsProps = WithActionsChildren | WithActionsProps;
|
|
27
28
|
type Step = {
|
|
28
|
-
Root: React.ForwardRefExoticComponent<React.ComponentProps<typeof Popover.Content
|
|
29
|
+
Root: React.ForwardRefExoticComponent<React.ComponentProps<typeof Popover.Content> & {
|
|
30
|
+
withArrow?: boolean;
|
|
31
|
+
}>;
|
|
29
32
|
Title: (props: StepProps) => React.ReactNode;
|
|
30
33
|
Content: (props: StepProps) => React.ReactNode;
|
|
31
|
-
Actions: (props: ActionsProps
|
|
34
|
+
Actions: (props: ActionsProps & {
|
|
35
|
+
to?: string;
|
|
36
|
+
} & FlexProps) => React.ReactNode;
|
|
32
37
|
};
|
|
38
|
+
export declare const StepCount: ({ tourName }: {
|
|
39
|
+
tourName: ValidTourName;
|
|
40
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
33
41
|
declare const createStepComponents: (tourName: ValidTourName) => Step;
|
|
34
42
|
export type { Step };
|
|
35
43
|
export { createStepComponents };
|
|
@@ -2,26 +2,57 @@ import * as React from 'react';
|
|
|
2
2
|
import { type State, type Action } from './Context';
|
|
3
3
|
import { Step } from './Step';
|
|
4
4
|
declare const tours: {
|
|
5
|
-
readonly
|
|
5
|
+
readonly contentTypeBuilder: {
|
|
6
6
|
Introduction: React.ComponentType<{
|
|
7
7
|
children: React.ReactNode;
|
|
8
8
|
}>;
|
|
9
|
-
|
|
9
|
+
CollectionTypes: React.ComponentType<{
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}>;
|
|
12
|
+
SingleTypes: React.ComponentType<{
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}>;
|
|
15
|
+
Components: React.ComponentType<{
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}>;
|
|
18
|
+
Finish: React.ComponentType<{
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
readonly contentManager: {
|
|
23
|
+
Introduction: React.ComponentType<{
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
}>;
|
|
26
|
+
Finish: React.ComponentType<{
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
}>;
|
|
29
|
+
Fields: React.ComponentType<{
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
}>;
|
|
32
|
+
Publish: React.ComponentType<{
|
|
33
|
+
children: React.ReactNode;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
readonly apiTokens: {
|
|
37
|
+
Introduction: React.ComponentType<{
|
|
38
|
+
children: React.ReactNode;
|
|
39
|
+
}>;
|
|
40
|
+
Finish: React.ComponentType<{
|
|
41
|
+
children: React.ReactNode;
|
|
42
|
+
}>;
|
|
43
|
+
CreateAnAPIToken: React.ComponentType<{
|
|
44
|
+
children: React.ReactNode;
|
|
45
|
+
}>;
|
|
46
|
+
CopyAPIToken: React.ComponentType<{
|
|
10
47
|
children: React.ReactNode;
|
|
11
48
|
}>;
|
|
12
49
|
};
|
|
50
|
+
readonly strapiCloud: {};
|
|
13
51
|
};
|
|
14
52
|
type Tours = typeof tours;
|
|
15
53
|
type Content = (Step: Step, { state, dispatch, }: {
|
|
16
54
|
state: State;
|
|
17
55
|
dispatch: React.Dispatch<Action>;
|
|
18
56
|
}) => React.ReactNode;
|
|
19
|
-
export declare const GuidedTourOverlay: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<Omit<import("@strapi/design-system").TransientBoxProps & {
|
|
20
|
-
children?: React.ReactNode;
|
|
21
|
-
} & import("@strapi/design-system/dist/types").AsProp<React.ElementType<any, keyof React.JSX.IntrinsicElements>> & Omit<Omit<any, "ref">, "children" | keyof import("@strapi/design-system/dist/types").AsProp<C> | keyof import("@strapi/design-system").TransientBoxProps> & {
|
|
22
|
-
ref?: any;
|
|
23
|
-
}, "ref"> & {
|
|
24
|
-
ref?: any;
|
|
25
|
-
}, never>> & Omit<import("@strapi/design-system").BoxComponent<"div">, keyof React.Component<any, {}, any>>;
|
|
26
57
|
export type { Content, Tours };
|
|
27
58
|
export { tours };
|
|
@@ -14,7 +14,7 @@ type WidgetArgs = {
|
|
|
14
14
|
component: () => Promise<React.ComponentType>;
|
|
15
15
|
pluginId?: string;
|
|
16
16
|
id: string;
|
|
17
|
-
permissions?: Permission
|
|
17
|
+
permissions?: Array<Pick<Permission, 'action'> & Partial<Omit<Permission, 'action'>>>;
|
|
18
18
|
};
|
|
19
19
|
type Widget = Omit<WidgetArgs, 'id' | 'pluginId'> & {
|
|
20
20
|
uid: WidgetUID;
|
|
@@ -19,7 +19,7 @@ interface AuthContextValue {
|
|
|
19
19
|
* permission object form the API is returned. Therefore, if the list is
|
|
20
20
|
* empty, the user does not have any of those permissions.
|
|
21
21
|
*/
|
|
22
|
-
checkUserHasPermissions: (permissions?: Permission
|
|
22
|
+
checkUserHasPermissions: (permissions?: Array<Pick<Permission, 'action'> & Partial<Omit<Permission, 'action'>>>, passedPermissions?: Permission[], rawQueryContext?: string) => Promise<Permission[]>;
|
|
23
23
|
isLoading: boolean;
|
|
24
24
|
permissions: Permission[];
|
|
25
25
|
refetchPermissions: () => Promise<void>;
|
|
@@ -2,5 +2,6 @@ interface TokenBoxProps {
|
|
|
2
2
|
token?: string;
|
|
3
3
|
tokenType: 'transfer-token' | 'api-token';
|
|
4
4
|
}
|
|
5
|
+
export declare const UnstableApiTokenBox: ({ token, tokenType }: TokenBoxProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
6
|
export declare const TokenBox: ({ token, tokenType }: TokenBoxProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
7
|
export {};
|
|
@@ -3,5 +3,9 @@ import type { User } from '../features/Auth';
|
|
|
3
3
|
* Retrieves the display name of an admin panel user
|
|
4
4
|
*/
|
|
5
5
|
declare const getDisplayName: ({ firstname, lastname, username, email }?: Partial<User>) => string;
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves the initials of the user (based on their firstname / lastname or their display name)
|
|
8
|
+
*/
|
|
9
|
+
declare const getInitials: (user?: Partial<User>) => string;
|
|
6
10
|
declare const hashAdminUserEmail: (payload?: User) => Promise<string | null>;
|
|
7
|
-
export { getDisplayName, hashAdminUserEmail };
|
|
11
|
+
export { getDisplayName, getInitials, hashAdminUserEmail };
|
|
@@ -2,11 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
var constants = require('./constants.js');
|
|
4
4
|
|
|
5
|
+
const DEFAULT_ATTIBUTES = [
|
|
6
|
+
'createdAt',
|
|
7
|
+
'updatedAt',
|
|
8
|
+
'publishedAt',
|
|
9
|
+
'createdBy',
|
|
10
|
+
'updatedBy',
|
|
11
|
+
'locale',
|
|
12
|
+
'localizations'
|
|
13
|
+
];
|
|
5
14
|
const createGuidedTourService = ({ strapi })=>{
|
|
6
15
|
const getCompletedActions = async ()=>{
|
|
7
|
-
// Check if any content-type schemas have been
|
|
16
|
+
// Check if any content-type schemas have been created on the api:: namespace
|
|
8
17
|
const contentTypeSchemaNames = Object.keys(strapi.contentTypes).filter((contentTypeUid)=>contentTypeUid.startsWith('api::'));
|
|
9
|
-
const
|
|
18
|
+
const contentTypeSchemaAttributes = contentTypeSchemaNames.map((uid)=>{
|
|
19
|
+
const attributes = Object.keys(strapi.contentType(uid).attributes);
|
|
20
|
+
return attributes.filter((attribute)=>!DEFAULT_ATTIBUTES.includes(attribute));
|
|
21
|
+
});
|
|
22
|
+
const didCreateContentTypeSchema = (()=>{
|
|
23
|
+
if (contentTypeSchemaNames.length === 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return contentTypeSchemaAttributes.some((attributes)=>attributes.length > 0);
|
|
27
|
+
})();
|
|
10
28
|
// Check if any content has been created for content-types on the api:: namespace
|
|
11
29
|
const hasContent = await (async ()=>{
|
|
12
30
|
for (const name of contentTypeSchemaNames){
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guided-tour.js","sources":["../../../../../server/src/services/guided-tour.ts"],"sourcesContent":["import { Core, Internal } from '@strapi/types';\nimport constants from './constants';\n\nexport type GuidedTourRequiredActions = {\n didCreateContentTypeSchema: boolean;\n didCreateContent: boolean;\n didCreateApiToken: boolean;\n};\nexport type GuidedTourCompletedActions = keyof GuidedTourRequiredActions;\n\nexport const createGuidedTourService = ({ strapi }: { strapi: Core.Strapi }) => {\n const getCompletedActions = async () => {\n // Check if any content-type schemas have been
|
|
1
|
+
{"version":3,"file":"guided-tour.js","sources":["../../../../../server/src/services/guided-tour.ts"],"sourcesContent":["import { Core, Internal } from '@strapi/types';\nimport constants from './constants';\n\nexport type GuidedTourRequiredActions = {\n didCreateContentTypeSchema: boolean;\n didCreateContent: boolean;\n didCreateApiToken: boolean;\n};\nexport type GuidedTourCompletedActions = keyof GuidedTourRequiredActions;\n\nconst DEFAULT_ATTIBUTES = [\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'locale',\n 'localizations',\n];\n\nexport const createGuidedTourService = ({ strapi }: { strapi: Core.Strapi }) => {\n const getCompletedActions = async () => {\n // Check if any content-type schemas have been created on the api:: namespace\n const contentTypeSchemaNames = Object.keys(strapi.contentTypes).filter((contentTypeUid) =>\n contentTypeUid.startsWith('api::')\n );\n const contentTypeSchemaAttributes = contentTypeSchemaNames.map((uid) => {\n const attributes = Object.keys(\n strapi.contentType(uid as Internal.UID.ContentType).attributes\n );\n return attributes.filter((attribute) => !DEFAULT_ATTIBUTES.includes(attribute));\n });\n const didCreateContentTypeSchema = (() => {\n if (contentTypeSchemaNames.length === 0) {\n return false;\n }\n return contentTypeSchemaAttributes.some((attributes) => attributes.length > 0);\n })();\n\n // Check if any content has been created for content-types on the api:: namespace\n const hasContent = await (async () => {\n for (const name of contentTypeSchemaNames) {\n const count = await strapi.documents(name as Internal.UID.ContentType).count({});\n\n if (count > 0) return true;\n }\n\n return false;\n })();\n const didCreateContent = didCreateContentTypeSchema && hasContent;\n\n // Check if any api tokens have been created besides the default ones\n const createdApiTokens = await strapi\n .documents('admin::api-token')\n .findMany({ fields: ['name', 'description'] });\n const didCreateApiToken = createdApiTokens.some((doc) =>\n constants.DEFAULT_API_TOKENS.every(\n (token) => token.name !== doc.name && token.description !== doc.description\n )\n );\n\n // Compute an array of action names that have been completed\n const requiredActions = {\n didCreateContentTypeSchema,\n didCreateContent,\n didCreateApiToken,\n };\n const requiredActionNames = Object.keys(requiredActions) as Array<GuidedTourCompletedActions>;\n const completedActions = requiredActionNames.filter((key) => requiredActions[key]);\n\n return completedActions;\n };\n\n return {\n getCompletedActions,\n };\n};\n"],"names":["DEFAULT_ATTIBUTES","createGuidedTourService","strapi","getCompletedActions","contentTypeSchemaNames","Object","keys","contentTypes","filter","contentTypeUid","startsWith","contentTypeSchemaAttributes","map","uid","attributes","contentType","attribute","includes","didCreateContentTypeSchema","length","some","hasContent","name","count","documents","didCreateContent","createdApiTokens","findMany","fields","didCreateApiToken","doc","constants","DEFAULT_API_TOKENS","every","token","description","requiredActions","requiredActionNames","completedActions","key"],"mappings":";;;;AAUA,MAAMA,iBAAoB,GAAA;AACxB,IAAA,WAAA;AACA,IAAA,WAAA;AACA,IAAA,aAAA;AACA,IAAA,WAAA;AACA,IAAA,WAAA;AACA,IAAA,QAAA;AACA,IAAA;AACD,CAAA;AAEYC,MAAAA,uBAAAA,GAA0B,CAAC,EAAEC,MAAM,EAA2B,GAAA;AACzE,IAAA,MAAMC,mBAAsB,GAAA,UAAA;;AAE1B,QAAA,MAAMC,sBAAyBC,GAAAA,MAAAA,CAAOC,IAAI,CAACJ,MAAOK,CAAAA,YAAY,CAAEC,CAAAA,MAAM,CAAC,CAACC,cACtEA,GAAAA,cAAAA,CAAeC,UAAU,CAAC,OAAA,CAAA,CAAA;AAE5B,QAAA,MAAMC,2BAA8BP,GAAAA,sBAAAA,CAAuBQ,GAAG,CAAC,CAACC,GAAAA,GAAAA;YAC9D,MAAMC,UAAAA,GAAaT,OAAOC,IAAI,CAC5BJ,OAAOa,WAAW,CAACF,KAAiCC,UAAU,CAAA;YAEhE,OAAOA,UAAAA,CAAWN,MAAM,CAAC,CAACQ,YAAc,CAAChB,iBAAAA,CAAkBiB,QAAQ,CAACD,SAAAA,CAAAA,CAAAA;AACtE,SAAA,CAAA;QACA,MAAME,0BAAAA,GAA6B,CAAC,IAAA;YAClC,IAAId,sBAAAA,CAAuBe,MAAM,KAAK,CAAG,EAAA;gBACvC,OAAO,KAAA;AACT;AACA,YAAA,OAAOR,4BAA4BS,IAAI,CAAC,CAACN,UAAeA,GAAAA,UAAAA,CAAWK,MAAM,GAAG,CAAA,CAAA;SAC9E,GAAA;;QAGA,MAAME,UAAAA,GAAa,MAAO,CAAA,UAAA;YACxB,KAAK,MAAMC,QAAQlB,sBAAwB,CAAA;gBACzC,MAAMmB,KAAAA,GAAQ,MAAMrB,MAAOsB,CAAAA,SAAS,CAACF,IAAkCC,CAAAA,CAAAA,KAAK,CAAC,EAAC,CAAA;gBAE9E,IAAIA,KAAAA,GAAQ,GAAG,OAAO,IAAA;AACxB;YAEA,OAAO,KAAA;SACT,GAAA;AACA,QAAA,MAAME,mBAAmBP,0BAA8BG,IAAAA,UAAAA;;AAGvD,QAAA,MAAMK,mBAAmB,MAAMxB,MAAAA,CAC5BsB,SAAS,CAAC,kBAAA,CAAA,CACVG,QAAQ,CAAC;YAAEC,MAAQ,EAAA;AAAC,gBAAA,MAAA;AAAQ,gBAAA;AAAc;AAAC,SAAA,CAAA;QAC9C,MAAMC,iBAAAA,GAAoBH,iBAAiBN,IAAI,CAAC,CAACU,GAC/CC,GAAAA,SAAAA,CAAUC,kBAAkB,CAACC,KAAK,CAChC,CAACC,KAAUA,GAAAA,KAAAA,CAAMZ,IAAI,KAAKQ,GAAIR,CAAAA,IAAI,IAAIY,KAAMC,CAAAA,WAAW,KAAKL,GAAAA,CAAIK,WAAW,CAAA,CAAA;;AAK/E,QAAA,MAAMC,eAAkB,GAAA;AACtBlB,YAAAA,0BAAAA;AACAO,YAAAA,gBAAAA;AACAI,YAAAA;AACF,SAAA;QACA,MAAMQ,mBAAAA,GAAsBhC,MAAOC,CAAAA,IAAI,CAAC8B,eAAAA,CAAAA;QACxC,MAAME,gBAAAA,GAAmBD,oBAAoB7B,MAAM,CAAC,CAAC+B,GAAQH,GAAAA,eAAe,CAACG,GAAI,CAAA,CAAA;QAEjF,OAAOD,gBAAAA;AACT,KAAA;IAEA,OAAO;AACLnC,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
import constants from './constants.mjs';
|
|
2
2
|
|
|
3
|
+
const DEFAULT_ATTIBUTES = [
|
|
4
|
+
'createdAt',
|
|
5
|
+
'updatedAt',
|
|
6
|
+
'publishedAt',
|
|
7
|
+
'createdBy',
|
|
8
|
+
'updatedBy',
|
|
9
|
+
'locale',
|
|
10
|
+
'localizations'
|
|
11
|
+
];
|
|
3
12
|
const createGuidedTourService = ({ strapi })=>{
|
|
4
13
|
const getCompletedActions = async ()=>{
|
|
5
|
-
// Check if any content-type schemas have been
|
|
14
|
+
// Check if any content-type schemas have been created on the api:: namespace
|
|
6
15
|
const contentTypeSchemaNames = Object.keys(strapi.contentTypes).filter((contentTypeUid)=>contentTypeUid.startsWith('api::'));
|
|
7
|
-
const
|
|
16
|
+
const contentTypeSchemaAttributes = contentTypeSchemaNames.map((uid)=>{
|
|
17
|
+
const attributes = Object.keys(strapi.contentType(uid).attributes);
|
|
18
|
+
return attributes.filter((attribute)=>!DEFAULT_ATTIBUTES.includes(attribute));
|
|
19
|
+
});
|
|
20
|
+
const didCreateContentTypeSchema = (()=>{
|
|
21
|
+
if (contentTypeSchemaNames.length === 0) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return contentTypeSchemaAttributes.some((attributes)=>attributes.length > 0);
|
|
25
|
+
})();
|
|
8
26
|
// Check if any content has been created for content-types on the api:: namespace
|
|
9
27
|
const hasContent = await (async ()=>{
|
|
10
28
|
for (const name of contentTypeSchemaNames){
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guided-tour.mjs","sources":["../../../../../server/src/services/guided-tour.ts"],"sourcesContent":["import { Core, Internal } from '@strapi/types';\nimport constants from './constants';\n\nexport type GuidedTourRequiredActions = {\n didCreateContentTypeSchema: boolean;\n didCreateContent: boolean;\n didCreateApiToken: boolean;\n};\nexport type GuidedTourCompletedActions = keyof GuidedTourRequiredActions;\n\nexport const createGuidedTourService = ({ strapi }: { strapi: Core.Strapi }) => {\n const getCompletedActions = async () => {\n // Check if any content-type schemas have been
|
|
1
|
+
{"version":3,"file":"guided-tour.mjs","sources":["../../../../../server/src/services/guided-tour.ts"],"sourcesContent":["import { Core, Internal } from '@strapi/types';\nimport constants from './constants';\n\nexport type GuidedTourRequiredActions = {\n didCreateContentTypeSchema: boolean;\n didCreateContent: boolean;\n didCreateApiToken: boolean;\n};\nexport type GuidedTourCompletedActions = keyof GuidedTourRequiredActions;\n\nconst DEFAULT_ATTIBUTES = [\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'locale',\n 'localizations',\n];\n\nexport const createGuidedTourService = ({ strapi }: { strapi: Core.Strapi }) => {\n const getCompletedActions = async () => {\n // Check if any content-type schemas have been created on the api:: namespace\n const contentTypeSchemaNames = Object.keys(strapi.contentTypes).filter((contentTypeUid) =>\n contentTypeUid.startsWith('api::')\n );\n const contentTypeSchemaAttributes = contentTypeSchemaNames.map((uid) => {\n const attributes = Object.keys(\n strapi.contentType(uid as Internal.UID.ContentType).attributes\n );\n return attributes.filter((attribute) => !DEFAULT_ATTIBUTES.includes(attribute));\n });\n const didCreateContentTypeSchema = (() => {\n if (contentTypeSchemaNames.length === 0) {\n return false;\n }\n return contentTypeSchemaAttributes.some((attributes) => attributes.length > 0);\n })();\n\n // Check if any content has been created for content-types on the api:: namespace\n const hasContent = await (async () => {\n for (const name of contentTypeSchemaNames) {\n const count = await strapi.documents(name as Internal.UID.ContentType).count({});\n\n if (count > 0) return true;\n }\n\n return false;\n })();\n const didCreateContent = didCreateContentTypeSchema && hasContent;\n\n // Check if any api tokens have been created besides the default ones\n const createdApiTokens = await strapi\n .documents('admin::api-token')\n .findMany({ fields: ['name', 'description'] });\n const didCreateApiToken = createdApiTokens.some((doc) =>\n constants.DEFAULT_API_TOKENS.every(\n (token) => token.name !== doc.name && token.description !== doc.description\n )\n );\n\n // Compute an array of action names that have been completed\n const requiredActions = {\n didCreateContentTypeSchema,\n didCreateContent,\n didCreateApiToken,\n };\n const requiredActionNames = Object.keys(requiredActions) as Array<GuidedTourCompletedActions>;\n const completedActions = requiredActionNames.filter((key) => requiredActions[key]);\n\n return completedActions;\n };\n\n return {\n getCompletedActions,\n };\n};\n"],"names":["DEFAULT_ATTIBUTES","createGuidedTourService","strapi","getCompletedActions","contentTypeSchemaNames","Object","keys","contentTypes","filter","contentTypeUid","startsWith","contentTypeSchemaAttributes","map","uid","attributes","contentType","attribute","includes","didCreateContentTypeSchema","length","some","hasContent","name","count","documents","didCreateContent","createdApiTokens","findMany","fields","didCreateApiToken","doc","constants","DEFAULT_API_TOKENS","every","token","description","requiredActions","requiredActionNames","completedActions","key"],"mappings":";;AAUA,MAAMA,iBAAoB,GAAA;AACxB,IAAA,WAAA;AACA,IAAA,WAAA;AACA,IAAA,aAAA;AACA,IAAA,WAAA;AACA,IAAA,WAAA;AACA,IAAA,QAAA;AACA,IAAA;AACD,CAAA;AAEYC,MAAAA,uBAAAA,GAA0B,CAAC,EAAEC,MAAM,EAA2B,GAAA;AACzE,IAAA,MAAMC,mBAAsB,GAAA,UAAA;;AAE1B,QAAA,MAAMC,sBAAyBC,GAAAA,MAAAA,CAAOC,IAAI,CAACJ,MAAOK,CAAAA,YAAY,CAAEC,CAAAA,MAAM,CAAC,CAACC,cACtEA,GAAAA,cAAAA,CAAeC,UAAU,CAAC,OAAA,CAAA,CAAA;AAE5B,QAAA,MAAMC,2BAA8BP,GAAAA,sBAAAA,CAAuBQ,GAAG,CAAC,CAACC,GAAAA,GAAAA;YAC9D,MAAMC,UAAAA,GAAaT,OAAOC,IAAI,CAC5BJ,OAAOa,WAAW,CAACF,KAAiCC,UAAU,CAAA;YAEhE,OAAOA,UAAAA,CAAWN,MAAM,CAAC,CAACQ,YAAc,CAAChB,iBAAAA,CAAkBiB,QAAQ,CAACD,SAAAA,CAAAA,CAAAA;AACtE,SAAA,CAAA;QACA,MAAME,0BAAAA,GAA6B,CAAC,IAAA;YAClC,IAAId,sBAAAA,CAAuBe,MAAM,KAAK,CAAG,EAAA;gBACvC,OAAO,KAAA;AACT;AACA,YAAA,OAAOR,4BAA4BS,IAAI,CAAC,CAACN,UAAeA,GAAAA,UAAAA,CAAWK,MAAM,GAAG,CAAA,CAAA;SAC9E,GAAA;;QAGA,MAAME,UAAAA,GAAa,MAAO,CAAA,UAAA;YACxB,KAAK,MAAMC,QAAQlB,sBAAwB,CAAA;gBACzC,MAAMmB,KAAAA,GAAQ,MAAMrB,MAAOsB,CAAAA,SAAS,CAACF,IAAkCC,CAAAA,CAAAA,KAAK,CAAC,EAAC,CAAA;gBAE9E,IAAIA,KAAAA,GAAQ,GAAG,OAAO,IAAA;AACxB;YAEA,OAAO,KAAA;SACT,GAAA;AACA,QAAA,MAAME,mBAAmBP,0BAA8BG,IAAAA,UAAAA;;AAGvD,QAAA,MAAMK,mBAAmB,MAAMxB,MAAAA,CAC5BsB,SAAS,CAAC,kBAAA,CAAA,CACVG,QAAQ,CAAC;YAAEC,MAAQ,EAAA;AAAC,gBAAA,MAAA;AAAQ,gBAAA;AAAc;AAAC,SAAA,CAAA;QAC9C,MAAMC,iBAAAA,GAAoBH,iBAAiBN,IAAI,CAAC,CAACU,GAC/CC,GAAAA,SAAAA,CAAUC,kBAAkB,CAACC,KAAK,CAChC,CAACC,KAAUA,GAAAA,KAAAA,CAAMZ,IAAI,KAAKQ,GAAIR,CAAAA,IAAI,IAAIY,KAAMC,CAAAA,WAAW,KAAKL,GAAAA,CAAIK,WAAW,CAAA,CAAA;;AAK/E,QAAA,MAAMC,eAAkB,GAAA;AACtBlB,YAAAA,0BAAAA;AACAO,YAAAA,gBAAAA;AACAI,YAAAA;AACF,SAAA;QACA,MAAMQ,mBAAAA,GAAsBhC,MAAOC,CAAAA,IAAI,CAAC8B,eAAAA,CAAAA;QACxC,MAAME,gBAAAA,GAAmBD,oBAAoB7B,MAAM,CAAC,CAAC+B,GAAQH,GAAAA,eAAe,CAACG,GAAI,CAAA,CAAA;QAEjF,OAAOD,gBAAAA;AACT,KAAA;IAEA,OAAO;AACLnC,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -51,10 +51,21 @@ const extractToken = (ctx)=>{
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
if (!fp.isNil(apiToken.lastUsedAt)) {
|
|
55
|
+
// update lastUsedAt if the token has not been used in the last hour
|
|
56
|
+
const hoursSinceLastUsed = dateFns.differenceInHours(currentDate, dateFns.parseISO(apiToken.lastUsedAt));
|
|
57
|
+
if (hoursSinceLastUsed >= 1) {
|
|
58
|
+
await strapi.db.query('admin::api-token').update({
|
|
59
|
+
where: {
|
|
60
|
+
id: apiToken.id
|
|
61
|
+
},
|
|
62
|
+
data: {
|
|
63
|
+
lastUsedAt: currentDate
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
// If lastUsedAt is not set, initialize it to the current date
|
|
58
69
|
await strapi.db.query('admin::api-token').update({
|
|
59
70
|
where: {
|
|
60
71
|
id: apiToken.id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-token.js","sources":["../../../../../server/src/strategies/api-token.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { castArray, isNil } from 'lodash/fp';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport constants from '../services/constants';\nimport { getService } from '../utils';\nimport '@strapi/types';\n\nconst { UnauthorizedError, ForbiddenError } = errors;\n\nconst isReadScope = (scope: any) => scope.endsWith('find') || scope.endsWith('findOne');\n\nconst extractToken = (ctx: Context) => {\n if (ctx.request && ctx.request.header && ctx.request.header.authorization) {\n const parts = ctx.request.header.authorization.split(/\\s+/);\n\n if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {\n return null;\n }\n\n return parts[1];\n }\n\n return null;\n};\n\n/**\n * Authenticate the validity of the token\n */\nexport const authenticate = async (ctx: Context) => {\n const apiTokenService = getService('api-token');\n const token = extractToken(ctx);\n\n if (!token) {\n return { authenticated: false };\n }\n\n const apiToken = await apiTokenService.getBy({\n accessKey: apiTokenService.hash(token),\n });\n\n // token not found\n if (!apiToken) {\n return { authenticated: false };\n }\n\n const currentDate = new Date();\n\n if (!isNil(apiToken.expiresAt)) {\n const expirationDate = new Date(apiToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n return { authenticated: false, error: new UnauthorizedError('Token expired') };\n }\n }\n\n // update lastUsedAt if the token has not been used in the last hour\n
|
|
1
|
+
{"version":3,"file":"api-token.js","sources":["../../../../../server/src/strategies/api-token.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { castArray, isNil } from 'lodash/fp';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport constants from '../services/constants';\nimport { getService } from '../utils';\nimport '@strapi/types';\n\nconst { UnauthorizedError, ForbiddenError } = errors;\n\nconst isReadScope = (scope: any) => scope.endsWith('find') || scope.endsWith('findOne');\n\nconst extractToken = (ctx: Context) => {\n if (ctx.request && ctx.request.header && ctx.request.header.authorization) {\n const parts = ctx.request.header.authorization.split(/\\s+/);\n\n if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {\n return null;\n }\n\n return parts[1];\n }\n\n return null;\n};\n\n/**\n * Authenticate the validity of the token\n */\nexport const authenticate = async (ctx: Context) => {\n const apiTokenService = getService('api-token');\n const token = extractToken(ctx);\n\n if (!token) {\n return { authenticated: false };\n }\n\n const apiToken = await apiTokenService.getBy({\n accessKey: apiTokenService.hash(token),\n });\n\n // token not found\n if (!apiToken) {\n return { authenticated: false };\n }\n\n const currentDate = new Date();\n\n if (!isNil(apiToken.expiresAt)) {\n const expirationDate = new Date(apiToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n return { authenticated: false, error: new UnauthorizedError('Token expired') };\n }\n }\n\n if (!isNil(apiToken.lastUsedAt)) {\n // update lastUsedAt if the token has not been used in the last hour\n const hoursSinceLastUsed = differenceInHours(currentDate, parseISO(apiToken.lastUsedAt));\n if (hoursSinceLastUsed >= 1) {\n await strapi.db.query('admin::api-token').update({\n where: { id: apiToken.id },\n data: { lastUsedAt: currentDate },\n });\n }\n } else {\n // If lastUsedAt is not set, initialize it to the current date\n await strapi.db.query('admin::api-token').update({\n where: { id: apiToken.id },\n data: { lastUsedAt: currentDate },\n });\n }\n\n if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {\n const ability = await strapi.contentAPI.permissions.engine.generateAbility(\n apiToken.permissions.map((action: any) => ({ action }))\n );\n\n return { authenticated: true, ability, credentials: apiToken };\n }\n\n return { authenticated: true, credentials: apiToken };\n};\n\n/**\n * Verify the token has the required abilities for the requested scope\n *\n * @type {import('.').VerifyFunction}\n */\nexport const verify = (auth: any, config: any) => {\n const { credentials: apiToken, ability } = auth;\n\n if (!apiToken) {\n throw new UnauthorizedError('Token not found');\n }\n\n const currentDate = new Date();\n\n if (!isNil(apiToken.expiresAt)) {\n const expirationDate = new Date(apiToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n throw new UnauthorizedError('Token expired');\n }\n }\n\n // Full access\n if (apiToken.type === constants.API_TOKEN_TYPE.FULL_ACCESS) {\n return;\n }\n\n // Read only\n if (apiToken.type === constants.API_TOKEN_TYPE.READ_ONLY) {\n /**\n * If you don't have `full-access` you can only access `find` and `findOne`\n * scopes. If the route has no scope, then you can't get access to it.\n */\n const scopes = castArray(config.scope);\n\n if (config.scope && scopes.every(isReadScope)) {\n return;\n }\n }\n\n // Custom\n else if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {\n if (!ability) {\n throw new ForbiddenError();\n }\n\n const scopes = castArray(config.scope);\n\n const isAllowed = scopes.every((scope) => ability.can(scope));\n\n if (isAllowed) {\n return;\n }\n }\n\n throw new ForbiddenError();\n};\n\nexport const name = 'api-token';\n\nexport default {\n name: 'api-token',\n authenticate,\n verify,\n};\n"],"names":["UnauthorizedError","ForbiddenError","errors","isReadScope","scope","endsWith","extractToken","ctx","request","header","authorization","parts","split","toLowerCase","length","authenticate","apiTokenService","getService","token","authenticated","apiToken","getBy","accessKey","hash","currentDate","Date","isNil","expiresAt","expirationDate","error","lastUsedAt","hoursSinceLastUsed","differenceInHours","parseISO","strapi","db","query","update","where","id","data","type","constants","API_TOKEN_TYPE","CUSTOM","ability","contentAPI","permissions","engine","generateAbility","map","action","credentials","verify","auth","config","FULL_ACCESS","READ_ONLY","scopes","castArray","every","isAllowed","can","name"],"mappings":"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"}
|
|
@@ -47,10 +47,21 @@ const extractToken = (ctx)=>{
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if (!isNil(apiToken.lastUsedAt)) {
|
|
51
|
+
// update lastUsedAt if the token has not been used in the last hour
|
|
52
|
+
const hoursSinceLastUsed = differenceInHours(currentDate, parseISO(apiToken.lastUsedAt));
|
|
53
|
+
if (hoursSinceLastUsed >= 1) {
|
|
54
|
+
await strapi.db.query('admin::api-token').update({
|
|
55
|
+
where: {
|
|
56
|
+
id: apiToken.id
|
|
57
|
+
},
|
|
58
|
+
data: {
|
|
59
|
+
lastUsedAt: currentDate
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
// If lastUsedAt is not set, initialize it to the current date
|
|
54
65
|
await strapi.db.query('admin::api-token').update({
|
|
55
66
|
where: {
|
|
56
67
|
id: apiToken.id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-token.mjs","sources":["../../../../../server/src/strategies/api-token.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { castArray, isNil } from 'lodash/fp';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport constants from '../services/constants';\nimport { getService } from '../utils';\nimport '@strapi/types';\n\nconst { UnauthorizedError, ForbiddenError } = errors;\n\nconst isReadScope = (scope: any) => scope.endsWith('find') || scope.endsWith('findOne');\n\nconst extractToken = (ctx: Context) => {\n if (ctx.request && ctx.request.header && ctx.request.header.authorization) {\n const parts = ctx.request.header.authorization.split(/\\s+/);\n\n if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {\n return null;\n }\n\n return parts[1];\n }\n\n return null;\n};\n\n/**\n * Authenticate the validity of the token\n */\nexport const authenticate = async (ctx: Context) => {\n const apiTokenService = getService('api-token');\n const token = extractToken(ctx);\n\n if (!token) {\n return { authenticated: false };\n }\n\n const apiToken = await apiTokenService.getBy({\n accessKey: apiTokenService.hash(token),\n });\n\n // token not found\n if (!apiToken) {\n return { authenticated: false };\n }\n\n const currentDate = new Date();\n\n if (!isNil(apiToken.expiresAt)) {\n const expirationDate = new Date(apiToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n return { authenticated: false, error: new UnauthorizedError('Token expired') };\n }\n }\n\n // update lastUsedAt if the token has not been used in the last hour\n
|
|
1
|
+
{"version":3,"file":"api-token.mjs","sources":["../../../../../server/src/strategies/api-token.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { castArray, isNil } from 'lodash/fp';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport constants from '../services/constants';\nimport { getService } from '../utils';\nimport '@strapi/types';\n\nconst { UnauthorizedError, ForbiddenError } = errors;\n\nconst isReadScope = (scope: any) => scope.endsWith('find') || scope.endsWith('findOne');\n\nconst extractToken = (ctx: Context) => {\n if (ctx.request && ctx.request.header && ctx.request.header.authorization) {\n const parts = ctx.request.header.authorization.split(/\\s+/);\n\n if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {\n return null;\n }\n\n return parts[1];\n }\n\n return null;\n};\n\n/**\n * Authenticate the validity of the token\n */\nexport const authenticate = async (ctx: Context) => {\n const apiTokenService = getService('api-token');\n const token = extractToken(ctx);\n\n if (!token) {\n return { authenticated: false };\n }\n\n const apiToken = await apiTokenService.getBy({\n accessKey: apiTokenService.hash(token),\n });\n\n // token not found\n if (!apiToken) {\n return { authenticated: false };\n }\n\n const currentDate = new Date();\n\n if (!isNil(apiToken.expiresAt)) {\n const expirationDate = new Date(apiToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n return { authenticated: false, error: new UnauthorizedError('Token expired') };\n }\n }\n\n if (!isNil(apiToken.lastUsedAt)) {\n // update lastUsedAt if the token has not been used in the last hour\n const hoursSinceLastUsed = differenceInHours(currentDate, parseISO(apiToken.lastUsedAt));\n if (hoursSinceLastUsed >= 1) {\n await strapi.db.query('admin::api-token').update({\n where: { id: apiToken.id },\n data: { lastUsedAt: currentDate },\n });\n }\n } else {\n // If lastUsedAt is not set, initialize it to the current date\n await strapi.db.query('admin::api-token').update({\n where: { id: apiToken.id },\n data: { lastUsedAt: currentDate },\n });\n }\n\n if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {\n const ability = await strapi.contentAPI.permissions.engine.generateAbility(\n apiToken.permissions.map((action: any) => ({ action }))\n );\n\n return { authenticated: true, ability, credentials: apiToken };\n }\n\n return { authenticated: true, credentials: apiToken };\n};\n\n/**\n * Verify the token has the required abilities for the requested scope\n *\n * @type {import('.').VerifyFunction}\n */\nexport const verify = (auth: any, config: any) => {\n const { credentials: apiToken, ability } = auth;\n\n if (!apiToken) {\n throw new UnauthorizedError('Token not found');\n }\n\n const currentDate = new Date();\n\n if (!isNil(apiToken.expiresAt)) {\n const expirationDate = new Date(apiToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n throw new UnauthorizedError('Token expired');\n }\n }\n\n // Full access\n if (apiToken.type === constants.API_TOKEN_TYPE.FULL_ACCESS) {\n return;\n }\n\n // Read only\n if (apiToken.type === constants.API_TOKEN_TYPE.READ_ONLY) {\n /**\n * If you don't have `full-access` you can only access `find` and `findOne`\n * scopes. If the route has no scope, then you can't get access to it.\n */\n const scopes = castArray(config.scope);\n\n if (config.scope && scopes.every(isReadScope)) {\n return;\n }\n }\n\n // Custom\n else if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {\n if (!ability) {\n throw new ForbiddenError();\n }\n\n const scopes = castArray(config.scope);\n\n const isAllowed = scopes.every((scope) => ability.can(scope));\n\n if (isAllowed) {\n return;\n }\n }\n\n throw new ForbiddenError();\n};\n\nexport const name = 'api-token';\n\nexport default {\n name: 'api-token',\n authenticate,\n verify,\n};\n"],"names":["UnauthorizedError","ForbiddenError","errors","isReadScope","scope","endsWith","extractToken","ctx","request","header","authorization","parts","split","toLowerCase","length","authenticate","apiTokenService","getService","token","authenticated","apiToken","getBy","accessKey","hash","currentDate","Date","isNil","expiresAt","expirationDate","error","lastUsedAt","hoursSinceLastUsed","differenceInHours","parseISO","strapi","db","query","update","where","id","data","type","constants","API_TOKEN_TYPE","CUSTOM","ability","contentAPI","permissions","engine","generateAbility","map","action","credentials","verify","auth","config","FULL_ACCESS","READ_ONLY","scopes","castArray","every","isAllowed","can","name"],"mappings":"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"}
|