@strapi/admin 5.52.0 → 5.52.2
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/components/PageHelpers.js +7 -5
- package/dist/admin/admin/src/components/PageHelpers.js.map +1 -1
- package/dist/admin/admin/src/components/PageHelpers.mjs +7 -5
- package/dist/admin/admin/src/components/PageHelpers.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/AuthPage.js +14 -9
- package/dist/admin/admin/src/pages/Auth/AuthPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/AuthPage.mjs +15 -10
- package/dist/admin/admin/src/pages/Auth/AuthPage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/components/Login.js +2 -6
- package/dist/admin/admin/src/pages/Auth/components/Login.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/components/Login.mjs +2 -6
- package/dist/admin/admin/src/pages/Auth/components/Login.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/constants.js +24 -8
- package/dist/admin/admin/src/pages/Auth/constants.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/constants.mjs +23 -9
- package/dist/admin/admin/src/pages/Auth/constants.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Auth/utils.js +34 -0
- package/dist/admin/admin/src/pages/Auth/utils.js.map +1 -0
- package/dist/admin/admin/src/pages/Auth/utils.mjs +32 -0
- package/dist/admin/admin/src/pages/Auth/utils.mjs.map +1 -0
- package/dist/admin/admin/src/translations/pt-BR.json.js +1 -1
- package/dist/admin/admin/src/translations/pt-BR.json.mjs +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +4 -0
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +4 -0
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/admin/src/utils/rulesEngine.js +27 -9
- package/dist/admin/admin/src/utils/rulesEngine.js.map +1 -1
- package/dist/admin/admin/src/utils/rulesEngine.mjs +2 -2
- package/dist/admin/admin/src/utils/rulesEngine.mjs.map +1 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/pages/Auth/constants.d.ts +19 -5
- package/dist/admin/src/pages/Auth/utils.d.ts +7 -0
- package/dist/admin/src/utils/rulesEngine.d.ts +9 -13
- package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.js +22 -4
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs +22 -4
- package/dist/server/ee/server/src/audit-logs/services/audit-logs.mjs.map +1 -1
- package/dist/server/server/src/controllers/validation/schema.js +36 -16
- package/dist/server/server/src/controllers/validation/schema.js.map +1 -1
- package/dist/server/server/src/controllers/validation/schema.mjs +1 -1
- package/dist/server/server/src/controllers/validation/schema.mjs.map +1 -1
- package/dist/server/server/src/services/content-type.js +8 -3
- package/dist/server/server/src/services/content-type.js.map +1 -1
- package/dist/server/server/src/services/content-type.mjs +8 -3
- package/dist/server/server/src/services/content-type.mjs.map +1 -1
- package/dist/server/server/src/services/permission/queries.js +3 -1
- package/dist/server/server/src/services/permission/queries.js.map +1 -1
- package/dist/server/server/src/services/permission/queries.mjs +3 -1
- package/dist/server/server/src/services/permission/queries.mjs.map +1 -1
- package/dist/server/src/controllers/validation/schema.d.ts +8 -48
- package/dist/server/src/controllers/validation/schema.d.ts.map +1 -1
- package/dist/server/src/services/content-type.d.ts.map +1 -1
- package/dist/server/src/services/permission/queries.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -149,15 +149,16 @@ const PageMain = ({ children, ...restProps })=>{
|
|
|
149
149
|
/**
|
|
150
150
|
* @public
|
|
151
151
|
* @description A wrapper component that should be used to protect a page. It will check the permissions
|
|
152
|
-
* you pass to it and render the children if the user
|
|
153
|
-
*
|
|
154
|
-
*
|
|
152
|
+
* you pass to it and render the children if any of the user's matching permissions grants access. If none do,
|
|
153
|
+
* it renders the NoPermissions component. Whilst these checks happen it will render the loading component
|
|
154
|
+
* and should the check fail it will render the error component with a notification.
|
|
155
155
|
*/ const Protect = ({ permissions = [], children })=>{
|
|
156
156
|
const userPermissions = Auth.useAuth('Protect', (state)=>state.permissions);
|
|
157
157
|
const { toggleNotification } = Notifications.useNotification();
|
|
158
158
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler.useAPIErrorHandler();
|
|
159
159
|
const matchingPermissions = (userPermissions || []).filter((permission)=>permissions.findIndex((perm)=>perm.action === permission.action && perm.subject === permission.subject) >= 0);
|
|
160
|
-
const
|
|
160
|
+
const hasConditions = (permission)=>Array.isArray(permission.conditions) && permission.conditions.length > 0;
|
|
161
|
+
const shouldCheckConditions = matchingPermissions.some(hasConditions);
|
|
161
162
|
const { isLoading, error, data } = auth.useCheckPermissionsQuery({
|
|
162
163
|
permissions: matchingPermissions.map((perm)=>({
|
|
163
164
|
action: perm.action,
|
|
@@ -185,7 +186,8 @@ const PageMain = ({ children, ...restProps })=>{
|
|
|
185
186
|
return /*#__PURE__*/ jsxRuntime.jsx(Error, {});
|
|
186
187
|
}
|
|
187
188
|
const { data: permissionsData } = data || {};
|
|
188
|
-
const
|
|
189
|
+
const hasUnconditionedPermission = matchingPermissions.some((permission)=>!hasConditions(permission));
|
|
190
|
+
const canAccess = hasUnconditionedPermission || (permissionsData ?? []).some((perm)=>perm === true);
|
|
189
191
|
if (!canAccess) {
|
|
190
192
|
return /*#__PURE__*/ jsxRuntime.jsx(NoPermissions, {});
|
|
191
193
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHelpers.js","sources":["../../../../../admin/src/components/PageHelpers.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Box,\n EmptyStateLayout,\n type EmptyStateLayoutProps,\n Flex,\n Loader,\n Main,\n MainProps,\n} from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { EmptyPermissions, EmptyDocuments } from '@strapi/icons/symbols';\nimport { useIntl } from 'react-intl';\n\nimport { useAuth, Permission } from '../features/Auth';\nimport { useNotification } from '../features/Notifications';\nimport { useAPIErrorHandler } from '../hooks/useAPIErrorHandler';\nimport { useCheckPermissionsQuery } from '../services/auth';\n\n/* -------------------------------------------------------------------------------------------------\n * Main\n * -----------------------------------------------------------------------------------------------*/\ninterface PageMainProps extends MainProps {\n children: React.ReactNode;\n}\n\nconst PageMain = ({ children, ...restProps }: PageMainProps) => {\n return <Main {...restProps}>{children}</Main>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Loading\n * -----------------------------------------------------------------------------------------------*/\ninterface LoadingProps {\n /**\n * @default 'Loading content.'\n */\n children?: React.ReactNode;\n}\n\n/**\n * @public\n * @description A loading component that should be rendered as the page\n * whilst you load the content for the aforementioned page.\n */\nconst Loading = ({ children = 'Loading content.' }: LoadingProps) => {\n return (\n <PageMain height=\"100dvh\" aria-busy={true}>\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Loader>{children}</Loader>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Error\n * -----------------------------------------------------------------------------------------------*/\ninterface ErrorProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * TODO: should we start passing our errors here so they're persisted on the screen?\n * This could follow something similar to how the global app error works...?\n */\n\n/**\n * @public\n * @description An error component that should be rendered as the page\n * when an error occurs.\n */\nconst Error = (props: ErrorProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <EmptyStateLayout\n icon={<WarningCircle width=\"16rem\" />}\n content={formatMessage({\n id: 'anErrorOccurred',\n defaultMessage: 'Whoops! Something went wrong. Please, try again.',\n })}\n {...props}\n />\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoPermissions\n * -----------------------------------------------------------------------------------------------*/\ninterface NoPermissionsProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when the user does not have the permissions to access the content.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoPermissions = (props: NoPermissionsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyPermissions width=\"16rem\" />}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-permissions',\n defaultMessage: \"You don't have the permissions to access that content\",\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoData\n * -----------------------------------------------------------------------------------------------*/\ninterface NoDataProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when there is no data available to display.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoData = (props: NoDataProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\" background=\"neutral100\">\n <Flex alignItems=\"center\" height=\"100%\" width=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyDocuments width=\"16rem\" />}\n action={props.action}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-document',\n defaultMessage: 'No content found',\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Protect\n * -----------------------------------------------------------------------------------------------*/\nexport interface ProtectProps {\n /**\n * The children to render if the user has the required permissions.\n * If providing a function, it will be called with an object containing\n * the permissions the user has based on the array you passed to the component.\n */\n children: React.ReactNode | ((args: { permissions: Permission[] }) => React.ReactNode);\n /**\n * The permissions the user needs to have to access the content.\n */\n permissions?: Array<Omit<Partial<Permission>, 'action'> & Pick<Permission, 'action'>>;\n}\n\n/**\n * @public\n * @description A wrapper component that should be used to protect a page. It will check the permissions\n * you pass to it and render the children if the user has the required permissions. If a user does not have ALL\n * the required permissions, it will redirect the user to the home page. Whilst these checks happen it will render\n * the loading component and should the check fail it will render the error component with a notification.\n */\nconst Protect = ({ permissions = [], children }: ProtectProps) => {\n const userPermissions = useAuth('Protect', (state) => state.permissions);\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const matchingPermissions = (userPermissions || []).filter(\n (permission) =>\n permissions.findIndex(\n (perm) => perm.action === permission.action && perm.subject === permission.subject\n ) >= 0\n );\n\n const shouldCheckConditions = matchingPermissions.some(\n (perm) => Array.isArray(perm.conditions) && perm.conditions.length > 0\n );\n\n const { isLoading, error, data } = useCheckPermissionsQuery(\n {\n permissions: matchingPermissions.map((perm) => ({\n action: perm.action,\n subject: perm.subject,\n })),\n },\n {\n skip: !shouldCheckConditions,\n }\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 if (isLoading) {\n return <Loading />;\n }\n\n if (error) {\n return <Error />;\n }\n\n const { data: permissionsData } = data || {};\n\n const canAccess =\n shouldCheckConditions && permissionsData\n ? !permissionsData.includes(false)\n : matchingPermissions.length > 0;\n\n if (!canAccess) {\n return <NoPermissions />;\n }\n\n return (\n <>\n {typeof children === 'function' ? children({ permissions: matchingPermissions }) : children}\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Title\n * -----------------------------------------------------------------------------------------------*/\nexport interface TitleProps {\n children: string;\n}\n\n/**\n * @public\n * @description This component takes the children (must be a string) and sets\n * it as the title of the html.\n */\nconst Title = ({ children: title }: TitleProps) => {\n React.useEffect(() => {\n document.title = `${title} | Strapi`;\n }, [title]);\n\n return null;\n};\n\nconst Page = {\n Error,\n Loading,\n NoPermissions,\n Protect,\n NoData,\n Main: PageMain,\n Title,\n};\n\nexport { Page };\nexport type { ErrorProps, LoadingProps, NoPermissionsProps, PageMainProps as MainProps };\n"],"names":["PageMain","children","restProps","_jsx","Main","Loading","height","aria-busy","Flex","alignItems","justifyContent","Loader","Error","props","formatMessage","useIntl","EmptyStateLayout","icon","WarningCircle","width","content","id","defaultMessage","NoPermissions","Box","minWidth","EmptyPermissions","NoData","background","EmptyDocuments","action","Protect","permissions","userPermissions","useAuth","state","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","matchingPermissions","filter","permission","findIndex","perm","subject","shouldCheckConditions","some","Array","isArray","conditions","length","isLoading","error","data","useCheckPermissionsQuery","map","skip","React","useEffect","type","message","permissionsData","canAccess","includes","_Fragment","Title","title","document","Page"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAMA,WAAW,CAAC,EAAEC,QAAQ,EAAE,GAAGC,SAAAA,EAA0B,GAAA;AACzD,IAAA,qBAAOC,cAAA,CAACC,iBAAAA,EAAAA;AAAM,QAAA,GAAGF,SAAS;AAAGD,QAAAA,QAAAA,EAAAA;;AAC/B,CAAA;AAYA;;;;AAIC,IACD,MAAMI,OAAAA,GAAU,CAAC,EAAEJ,QAAAA,GAAW,kBAAkB,EAAgB,GAAA;AAC9D,IAAA,qBACEE,cAAA,CAACH,QAAAA,EAAAA;QAASM,MAAAA,EAAO,QAAA;QAASC,WAAAA,EAAW,IAAA;AACnC,QAAA,QAAA,gBAAAJ,cAAA,CAACK,iBAAAA,EAAAA;YAAKC,UAAAA,EAAW,QAAA;YAASH,MAAAA,EAAO,MAAA;YAAOI,cAAAA,EAAe,QAAA;AACrD,YAAA,QAAA,gBAAAP,cAAA,CAACQ,mBAAAA,EAAAA;AAAQV,gBAAAA,QAAAA,EAAAA;;;;AAIjB,CAAA;AAOA;;;;;;;IAUA,MAAMW,QAAQ,CAACC,KAAAA,GAAAA;IACb,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,qBACEZ,cAAA,CAACH,QAAAA,EAAAA;QAASM,MAAAA,EAAO,MAAA;AACf,QAAA,QAAA,gBAAAH,cAAA,CAACK,iBAAAA,EAAAA;YAAKC,UAAAA,EAAW,QAAA;YAASH,MAAAA,EAAO,MAAA;YAAOI,cAAAA,EAAe,QAAA;AACrD,YAAA,QAAA,gBAAAP,cAAA,CAACa,6BAAAA,EAAAA;AACCC,gBAAAA,IAAAA,gBAAMd,cAAA,CAACe,mBAAAA,EAAAA;oBAAcC,KAAAA,EAAM;;AAC3BC,gBAAAA,OAAAA,EAASN,aAAAA,CAAc;oBACrBO,EAAAA,EAAI,iBAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA,CAAA;AACC,gBAAA,GAAGT;;;;AAKd,CAAA;AAOA;;;;;;IAOA,MAAMU,gBAAgB,CAACV,KAAAA,GAAAA;IACrB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,qBACEZ,cAAA,CAACH,QAAAA,EAAAA;QAASM,MAAAA,EAAO,MAAA;AACf,QAAA,QAAA,gBAAAH,cAAA,CAACK,iBAAAA,EAAAA;YAAKC,UAAAA,EAAW,QAAA;YAASH,MAAAA,EAAO,MAAA;YAAOI,cAAAA,EAAe,QAAA;AACrD,YAAA,QAAA,gBAAAP,cAAA,CAACqB,gBAAAA,EAAAA;gBAAIC,QAAAA,EAAS,KAAA;AACZ,gBAAA,QAAA,gBAAAtB,cAAA,CAACa,6BAAAA,EAAAA;AACCC,oBAAAA,IAAAA,gBAAMd,cAAA,CAACuB,wBAAAA,EAAAA;wBAAiBP,KAAAA,EAAM;;AAC9BC,oBAAAA,OAAAA,EAASN,aAAAA,CAAc;wBACrBO,EAAAA,EAAI,qDAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA,CAAA;AACC,oBAAA,GAAGT;;;;;AAMhB,CAAA;AAOA;;;;;;IAOA,MAAMc,SAAS,CAACd,KAAAA,GAAAA;IACd,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,qBACEZ,cAAA,CAACH,QAAAA,EAAAA;QAASM,MAAAA,EAAO,MAAA;QAAOsB,UAAAA,EAAW,YAAA;AACjC,QAAA,QAAA,gBAAAzB,cAAA,CAACK,iBAAAA,EAAAA;YAAKC,UAAAA,EAAW,QAAA;YAASH,MAAAA,EAAO,MAAA;YAAOa,KAAAA,EAAM,MAAA;YAAOT,cAAAA,EAAe,QAAA;AAClE,YAAA,QAAA,gBAAAP,cAAA,CAACqB,gBAAAA,EAAAA;gBAAIC,QAAAA,EAAS,KAAA;AACZ,gBAAA,QAAA,gBAAAtB,cAAA,CAACa,6BAAAA,EAAAA;AACCC,oBAAAA,IAAAA,gBAAMd,cAAA,CAAC0B,sBAAAA,EAAAA;wBAAeV,KAAAA,EAAM;;AAC5BW,oBAAAA,MAAAA,EAAQjB,MAAMiB,MAAM;AACpBV,oBAAAA,OAAAA,EAASN,aAAAA,CAAc;wBACrBO,EAAAA,EAAI,kDAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA,CAAA;AACC,oBAAA,GAAGT;;;;;AAMhB,CAAA;AAkBA;;;;;;IAOA,MAAMkB,UAAU,CAAC,EAAEC,cAAc,EAAE,EAAE/B,QAAQ,EAAgB,GAAA;AAC3D,IAAA,MAAMgC,kBAAkBC,YAAAA,CAAQ,SAAA,EAAW,CAACC,KAAAA,GAAUA,MAAMH,WAAW,CAAA;IACvE,MAAM,EAAEI,kBAAkB,EAAE,GAAGC,6BAAAA,EAAAA;AAC/B,IAAA,MAAM,EAAEC,uBAAAA,EAAyBC,cAAc,EAAE,GAAGC,qCAAAA,EAAAA;IAEpD,MAAMC,mBAAAA,GAAsB,CAACR,eAAAA,IAAmB,EAAE,EAAES,MAAM,CACxD,CAACC,UAAAA,GACCX,WAAAA,CAAYY,SAAS,CACnB,CAACC,IAAAA,GAASA,IAAAA,CAAKf,MAAM,KAAKa,UAAAA,CAAWb,MAAM,IAAIe,IAAAA,CAAKC,OAAO,KAAKH,UAAAA,CAAWG,OAAO,CAAA,IAC/E,CAAA,CAAA;AAGT,IAAA,MAAMC,wBAAwBN,mBAAAA,CAAoBO,IAAI,CACpD,CAACH,OAASI,KAAAA,CAAMC,OAAO,CAACL,IAAAA,CAAKM,UAAU,CAAA,IAAKN,IAAAA,CAAKM,UAAU,CAACC,MAAM,GAAG,CAAA,CAAA;IAGvE,MAAM,EAAEC,SAAS,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGC,6BAAAA,CACjC;AACExB,QAAAA,WAAAA,EAAaS,mBAAAA,CAAoBgB,GAAG,CAAC,CAACZ,QAAU;AAC9Cf,gBAAAA,MAAAA,EAAQe,KAAKf,MAAM;AACnBgB,gBAAAA,OAAAA,EAASD,KAAKC;aAChB,CAAA;KACF,EACA;AACEY,QAAAA,IAAAA,EAAM,CAACX;AACT,KAAA,CAAA;AAGFY,IAAAA,gBAAAA,CAAMC,SAAS,CAAC,IAAA;AACd,QAAA,IAAIN,KAAAA,EAAO;YACTlB,kBAAAA,CAAmB;gBACjByB,IAAAA,EAAM,QAAA;AACNC,gBAAAA,OAAAA,EAASvB,cAAAA,CAAee,KAAAA;AAC1B,aAAA,CAAA;AACF,QAAA;IACF,CAAA,EAAG;AAACA,QAAAA,KAAAA;AAAOf,QAAAA,cAAAA;AAAgBH,QAAAA;AAAmB,KAAA,CAAA;AAE9C,IAAA,IAAIiB,SAAAA,EAAW;AACb,QAAA,qBAAOlD,cAAA,CAACE,OAAAA,EAAAA,EAAAA,CAAAA;AACV,IAAA;AAEA,IAAA,IAAIiD,KAAAA,EAAO;AACT,QAAA,qBAAOnD,cAAA,CAACS,KAAAA,EAAAA,EAAAA,CAAAA;AACV,IAAA;AAEA,IAAA,MAAM,EAAE2C,IAAAA,EAAMQ,eAAe,EAAE,GAAGR,QAAQ,EAAC;IAE3C,MAAMS,SAAAA,GACJjB,qBAAAA,IAAyBgB,eAAAA,GACrB,CAACA,eAAAA,CAAgBE,QAAQ,CAAC,KAAA,CAAA,GAC1BxB,mBAAAA,CAAoBW,MAAM,GAAG,CAAA;AAEnC,IAAA,IAAI,CAACY,SAAAA,EAAW;AACd,QAAA,qBAAO7D,cAAA,CAACoB,aAAAA,EAAAA,EAAAA,CAAAA;AACV,IAAA;IAEA,qBACEpB,cAAA,CAAA+D,mBAAA,EAAA;kBACG,OAAOjE,QAAAA,KAAa,aAAaA,QAAAA,CAAS;YAAE+B,WAAAA,EAAaS;SAAoB,CAAA,GAAKxC;;AAGzF,CAAA;AASA;;;;AAIC,IACD,MAAMkE,KAAAA,GAAQ,CAAC,EAAElE,QAAAA,EAAUmE,KAAK,EAAc,GAAA;AAC5CT,IAAAA,gBAAAA,CAAMC,SAAS,CAAC,IAAA;AACdS,QAAAA,QAAAA,CAASD,KAAK,GAAG,CAAA,EAAGA,KAAAA,CAAM,SAAS,CAAC;IACtC,CAAA,EAAG;AAACA,QAAAA;AAAM,KAAA,CAAA;IAEV,OAAO,IAAA;AACT,CAAA;AAEA,MAAME,IAAAA,GAAO;AACX1D,IAAAA,KAAAA;AACAP,IAAAA,OAAAA;AACAkB,IAAAA,aAAAA;AACAQ,IAAAA,OAAAA;AACAJ,IAAAA,MAAAA;IACAvB,IAAAA,EAAMJ,QAAAA;AACNmE,IAAAA;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"PageHelpers.js","sources":["../../../../../admin/src/components/PageHelpers.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Box,\n EmptyStateLayout,\n type EmptyStateLayoutProps,\n Flex,\n Loader,\n Main,\n MainProps,\n} from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { EmptyPermissions, EmptyDocuments } from '@strapi/icons/symbols';\nimport { useIntl } from 'react-intl';\n\nimport { useAuth, Permission } from '../features/Auth';\nimport { useNotification } from '../features/Notifications';\nimport { useAPIErrorHandler } from '../hooks/useAPIErrorHandler';\nimport { useCheckPermissionsQuery } from '../services/auth';\n\n/* -------------------------------------------------------------------------------------------------\n * Main\n * -----------------------------------------------------------------------------------------------*/\ninterface PageMainProps extends MainProps {\n children: React.ReactNode;\n}\n\nconst PageMain = ({ children, ...restProps }: PageMainProps) => {\n return <Main {...restProps}>{children}</Main>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Loading\n * -----------------------------------------------------------------------------------------------*/\ninterface LoadingProps {\n /**\n * @default 'Loading content.'\n */\n children?: React.ReactNode;\n}\n\n/**\n * @public\n * @description A loading component that should be rendered as the page\n * whilst you load the content for the aforementioned page.\n */\nconst Loading = ({ children = 'Loading content.' }: LoadingProps) => {\n return (\n <PageMain height=\"100dvh\" aria-busy={true}>\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Loader>{children}</Loader>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Error\n * -----------------------------------------------------------------------------------------------*/\ninterface ErrorProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * TODO: should we start passing our errors here so they're persisted on the screen?\n * This could follow something similar to how the global app error works...?\n */\n\n/**\n * @public\n * @description An error component that should be rendered as the page\n * when an error occurs.\n */\nconst Error = (props: ErrorProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <EmptyStateLayout\n icon={<WarningCircle width=\"16rem\" />}\n content={formatMessage({\n id: 'anErrorOccurred',\n defaultMessage: 'Whoops! Something went wrong. Please, try again.',\n })}\n {...props}\n />\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoPermissions\n * -----------------------------------------------------------------------------------------------*/\ninterface NoPermissionsProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when the user does not have the permissions to access the content.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoPermissions = (props: NoPermissionsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyPermissions width=\"16rem\" />}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-permissions',\n defaultMessage: \"You don't have the permissions to access that content\",\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoData\n * -----------------------------------------------------------------------------------------------*/\ninterface NoDataProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when there is no data available to display.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoData = (props: NoDataProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\" background=\"neutral100\">\n <Flex alignItems=\"center\" height=\"100%\" width=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyDocuments width=\"16rem\" />}\n action={props.action}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-document',\n defaultMessage: 'No content found',\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Protect\n * -----------------------------------------------------------------------------------------------*/\nexport interface ProtectProps {\n /**\n * The children to render if the user has the required permissions.\n * If providing a function, it will be called with an object containing\n * the permissions the user has based on the array you passed to the component.\n */\n children: React.ReactNode | ((args: { permissions: Permission[] }) => React.ReactNode);\n /**\n * The permissions the user needs to have to access the content.\n */\n permissions?: Array<Omit<Partial<Permission>, 'action'> & Pick<Permission, 'action'>>;\n}\n\n/**\n * @public\n * @description A wrapper component that should be used to protect a page. It will check the permissions\n * you pass to it and render the children if any of the user's matching permissions grants access. If none do,\n * it renders the NoPermissions component. Whilst these checks happen it will render the loading component\n * and should the check fail it will render the error component with a notification.\n */\nconst Protect = ({ permissions = [], children }: ProtectProps) => {\n const userPermissions = useAuth('Protect', (state) => state.permissions);\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const matchingPermissions = (userPermissions || []).filter(\n (permission) =>\n permissions.findIndex(\n (perm) => perm.action === permission.action && perm.subject === permission.subject\n ) >= 0\n );\n\n const hasConditions = (permission: Permission) =>\n Array.isArray(permission.conditions) && permission.conditions.length > 0;\n\n const shouldCheckConditions = matchingPermissions.some(hasConditions);\n\n const { isLoading, error, data } = useCheckPermissionsQuery(\n {\n permissions: matchingPermissions.map((perm) => ({\n action: perm.action,\n subject: perm.subject,\n })),\n },\n {\n skip: !shouldCheckConditions,\n }\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 if (isLoading) {\n return <Loading />;\n }\n\n if (error) {\n return <Error />;\n }\n\n const { data: permissionsData } = data || {};\n\n const hasUnconditionedPermission = matchingPermissions.some(\n (permission) => !hasConditions(permission)\n );\n\n const canAccess =\n hasUnconditionedPermission || (permissionsData ?? []).some((perm) => perm === true);\n\n if (!canAccess) {\n return <NoPermissions />;\n }\n\n return (\n <>\n {typeof children === 'function' ? children({ permissions: matchingPermissions }) : children}\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Title\n * -----------------------------------------------------------------------------------------------*/\nexport interface TitleProps {\n children: string;\n}\n\n/**\n * @public\n * @description This component takes the children (must be a string) and sets\n * it as the title of the html.\n */\nconst Title = ({ children: title }: TitleProps) => {\n React.useEffect(() => {\n document.title = `${title} | Strapi`;\n }, [title]);\n\n return null;\n};\n\nconst Page = {\n Error,\n Loading,\n NoPermissions,\n Protect,\n NoData,\n Main: PageMain,\n Title,\n};\n\nexport { Page };\nexport type { ErrorProps, LoadingProps, NoPermissionsProps, PageMainProps as MainProps };\n"],"names":["PageMain","children","restProps","_jsx","Main","Loading","height","aria-busy","Flex","alignItems","justifyContent","Loader","Error","props","formatMessage","useIntl","EmptyStateLayout","icon","WarningCircle","width","content","id","defaultMessage","NoPermissions","Box","minWidth","EmptyPermissions","NoData","background","EmptyDocuments","action","Protect","permissions","userPermissions","useAuth","state","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","matchingPermissions","filter","permission","findIndex","perm","subject","hasConditions","Array","isArray","conditions","length","shouldCheckConditions","some","isLoading","error","data","useCheckPermissionsQuery","map","skip","React","useEffect","type","message","permissionsData","hasUnconditionedPermission","canAccess","_Fragment","Title","title","document","Page"],"mappings":"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"}
|
|
@@ -127,15 +127,16 @@ const PageMain = ({ children, ...restProps })=>{
|
|
|
127
127
|
/**
|
|
128
128
|
* @public
|
|
129
129
|
* @description A wrapper component that should be used to protect a page. It will check the permissions
|
|
130
|
-
* you pass to it and render the children if the user
|
|
131
|
-
*
|
|
132
|
-
*
|
|
130
|
+
* you pass to it and render the children if any of the user's matching permissions grants access. If none do,
|
|
131
|
+
* it renders the NoPermissions component. Whilst these checks happen it will render the loading component
|
|
132
|
+
* and should the check fail it will render the error component with a notification.
|
|
133
133
|
*/ const Protect = ({ permissions = [], children })=>{
|
|
134
134
|
const userPermissions = useAuth('Protect', (state)=>state.permissions);
|
|
135
135
|
const { toggleNotification } = useNotification();
|
|
136
136
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
|
137
137
|
const matchingPermissions = (userPermissions || []).filter((permission)=>permissions.findIndex((perm)=>perm.action === permission.action && perm.subject === permission.subject) >= 0);
|
|
138
|
-
const
|
|
138
|
+
const hasConditions = (permission)=>Array.isArray(permission.conditions) && permission.conditions.length > 0;
|
|
139
|
+
const shouldCheckConditions = matchingPermissions.some(hasConditions);
|
|
139
140
|
const { isLoading, error, data } = useCheckPermissionsQuery({
|
|
140
141
|
permissions: matchingPermissions.map((perm)=>({
|
|
141
142
|
action: perm.action,
|
|
@@ -163,7 +164,8 @@ const PageMain = ({ children, ...restProps })=>{
|
|
|
163
164
|
return /*#__PURE__*/ jsx(Error, {});
|
|
164
165
|
}
|
|
165
166
|
const { data: permissionsData } = data || {};
|
|
166
|
-
const
|
|
167
|
+
const hasUnconditionedPermission = matchingPermissions.some((permission)=>!hasConditions(permission));
|
|
168
|
+
const canAccess = hasUnconditionedPermission || (permissionsData ?? []).some((perm)=>perm === true);
|
|
167
169
|
if (!canAccess) {
|
|
168
170
|
return /*#__PURE__*/ jsx(NoPermissions, {});
|
|
169
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHelpers.mjs","sources":["../../../../../admin/src/components/PageHelpers.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Box,\n EmptyStateLayout,\n type EmptyStateLayoutProps,\n Flex,\n Loader,\n Main,\n MainProps,\n} from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { EmptyPermissions, EmptyDocuments } from '@strapi/icons/symbols';\nimport { useIntl } from 'react-intl';\n\nimport { useAuth, Permission } from '../features/Auth';\nimport { useNotification } from '../features/Notifications';\nimport { useAPIErrorHandler } from '../hooks/useAPIErrorHandler';\nimport { useCheckPermissionsQuery } from '../services/auth';\n\n/* -------------------------------------------------------------------------------------------------\n * Main\n * -----------------------------------------------------------------------------------------------*/\ninterface PageMainProps extends MainProps {\n children: React.ReactNode;\n}\n\nconst PageMain = ({ children, ...restProps }: PageMainProps) => {\n return <Main {...restProps}>{children}</Main>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Loading\n * -----------------------------------------------------------------------------------------------*/\ninterface LoadingProps {\n /**\n * @default 'Loading content.'\n */\n children?: React.ReactNode;\n}\n\n/**\n * @public\n * @description A loading component that should be rendered as the page\n * whilst you load the content for the aforementioned page.\n */\nconst Loading = ({ children = 'Loading content.' }: LoadingProps) => {\n return (\n <PageMain height=\"100dvh\" aria-busy={true}>\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Loader>{children}</Loader>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Error\n * -----------------------------------------------------------------------------------------------*/\ninterface ErrorProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * TODO: should we start passing our errors here so they're persisted on the screen?\n * This could follow something similar to how the global app error works...?\n */\n\n/**\n * @public\n * @description An error component that should be rendered as the page\n * when an error occurs.\n */\nconst Error = (props: ErrorProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <EmptyStateLayout\n icon={<WarningCircle width=\"16rem\" />}\n content={formatMessage({\n id: 'anErrorOccurred',\n defaultMessage: 'Whoops! Something went wrong. Please, try again.',\n })}\n {...props}\n />\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoPermissions\n * -----------------------------------------------------------------------------------------------*/\ninterface NoPermissionsProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when the user does not have the permissions to access the content.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoPermissions = (props: NoPermissionsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyPermissions width=\"16rem\" />}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-permissions',\n defaultMessage: \"You don't have the permissions to access that content\",\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoData\n * -----------------------------------------------------------------------------------------------*/\ninterface NoDataProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when there is no data available to display.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoData = (props: NoDataProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\" background=\"neutral100\">\n <Flex alignItems=\"center\" height=\"100%\" width=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyDocuments width=\"16rem\" />}\n action={props.action}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-document',\n defaultMessage: 'No content found',\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Protect\n * -----------------------------------------------------------------------------------------------*/\nexport interface ProtectProps {\n /**\n * The children to render if the user has the required permissions.\n * If providing a function, it will be called with an object containing\n * the permissions the user has based on the array you passed to the component.\n */\n children: React.ReactNode | ((args: { permissions: Permission[] }) => React.ReactNode);\n /**\n * The permissions the user needs to have to access the content.\n */\n permissions?: Array<Omit<Partial<Permission>, 'action'> & Pick<Permission, 'action'>>;\n}\n\n/**\n * @public\n * @description A wrapper component that should be used to protect a page. It will check the permissions\n * you pass to it and render the children if the user has the required permissions. If a user does not have ALL\n * the required permissions, it will redirect the user to the home page. Whilst these checks happen it will render\n * the loading component and should the check fail it will render the error component with a notification.\n */\nconst Protect = ({ permissions = [], children }: ProtectProps) => {\n const userPermissions = useAuth('Protect', (state) => state.permissions);\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const matchingPermissions = (userPermissions || []).filter(\n (permission) =>\n permissions.findIndex(\n (perm) => perm.action === permission.action && perm.subject === permission.subject\n ) >= 0\n );\n\n const shouldCheckConditions = matchingPermissions.some(\n (perm) => Array.isArray(perm.conditions) && perm.conditions.length > 0\n );\n\n const { isLoading, error, data } = useCheckPermissionsQuery(\n {\n permissions: matchingPermissions.map((perm) => ({\n action: perm.action,\n subject: perm.subject,\n })),\n },\n {\n skip: !shouldCheckConditions,\n }\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 if (isLoading) {\n return <Loading />;\n }\n\n if (error) {\n return <Error />;\n }\n\n const { data: permissionsData } = data || {};\n\n const canAccess =\n shouldCheckConditions && permissionsData\n ? !permissionsData.includes(false)\n : matchingPermissions.length > 0;\n\n if (!canAccess) {\n return <NoPermissions />;\n }\n\n return (\n <>\n {typeof children === 'function' ? children({ permissions: matchingPermissions }) : children}\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Title\n * -----------------------------------------------------------------------------------------------*/\nexport interface TitleProps {\n children: string;\n}\n\n/**\n * @public\n * @description This component takes the children (must be a string) and sets\n * it as the title of the html.\n */\nconst Title = ({ children: title }: TitleProps) => {\n React.useEffect(() => {\n document.title = `${title} | Strapi`;\n }, [title]);\n\n return null;\n};\n\nconst Page = {\n Error,\n Loading,\n NoPermissions,\n Protect,\n NoData,\n Main: PageMain,\n Title,\n};\n\nexport { Page };\nexport type { ErrorProps, LoadingProps, NoPermissionsProps, PageMainProps as MainProps };\n"],"names":["PageMain","children","restProps","_jsx","Main","Loading","height","aria-busy","Flex","alignItems","justifyContent","Loader","Error","props","formatMessage","useIntl","EmptyStateLayout","icon","WarningCircle","width","content","id","defaultMessage","NoPermissions","Box","minWidth","EmptyPermissions","NoData","background","EmptyDocuments","action","Protect","permissions","userPermissions","useAuth","state","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","matchingPermissions","filter","permission","findIndex","perm","subject","shouldCheckConditions","some","Array","isArray","conditions","length","isLoading","error","data","useCheckPermissionsQuery","map","skip","React","useEffect","type","message","permissionsData","canAccess","includes","_Fragment","Title","title","document","Page"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageHelpers.mjs","sources":["../../../../../admin/src/components/PageHelpers.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Box,\n EmptyStateLayout,\n type EmptyStateLayoutProps,\n Flex,\n Loader,\n Main,\n MainProps,\n} from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { EmptyPermissions, EmptyDocuments } from '@strapi/icons/symbols';\nimport { useIntl } from 'react-intl';\n\nimport { useAuth, Permission } from '../features/Auth';\nimport { useNotification } from '../features/Notifications';\nimport { useAPIErrorHandler } from '../hooks/useAPIErrorHandler';\nimport { useCheckPermissionsQuery } from '../services/auth';\n\n/* -------------------------------------------------------------------------------------------------\n * Main\n * -----------------------------------------------------------------------------------------------*/\ninterface PageMainProps extends MainProps {\n children: React.ReactNode;\n}\n\nconst PageMain = ({ children, ...restProps }: PageMainProps) => {\n return <Main {...restProps}>{children}</Main>;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Loading\n * -----------------------------------------------------------------------------------------------*/\ninterface LoadingProps {\n /**\n * @default 'Loading content.'\n */\n children?: React.ReactNode;\n}\n\n/**\n * @public\n * @description A loading component that should be rendered as the page\n * whilst you load the content for the aforementioned page.\n */\nconst Loading = ({ children = 'Loading content.' }: LoadingProps) => {\n return (\n <PageMain height=\"100dvh\" aria-busy={true}>\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Loader>{children}</Loader>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Error\n * -----------------------------------------------------------------------------------------------*/\ninterface ErrorProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * TODO: should we start passing our errors here so they're persisted on the screen?\n * This could follow something similar to how the global app error works...?\n */\n\n/**\n * @public\n * @description An error component that should be rendered as the page\n * when an error occurs.\n */\nconst Error = (props: ErrorProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <EmptyStateLayout\n icon={<WarningCircle width=\"16rem\" />}\n content={formatMessage({\n id: 'anErrorOccurred',\n defaultMessage: 'Whoops! Something went wrong. Please, try again.',\n })}\n {...props}\n />\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoPermissions\n * -----------------------------------------------------------------------------------------------*/\ninterface NoPermissionsProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when the user does not have the permissions to access the content.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoPermissions = (props: NoPermissionsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\">\n <Flex alignItems=\"center\" height=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyPermissions width=\"16rem\" />}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-permissions',\n defaultMessage: \"You don't have the permissions to access that content\",\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NoData\n * -----------------------------------------------------------------------------------------------*/\ninterface NoDataProps extends Partial<EmptyStateLayoutProps> {}\n\n/**\n * @public\n * @description A component that should be rendered as the page\n * when there is no data available to display.\n * This component does not check any permissions, it's up to you to decide\n * when it should be rendered.\n */\nconst NoData = (props: NoDataProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <PageMain height=\"100%\" background=\"neutral100\">\n <Flex alignItems=\"center\" height=\"100%\" width=\"100%\" justifyContent=\"center\">\n <Box minWidth=\"50%\">\n <EmptyStateLayout\n icon={<EmptyDocuments width=\"16rem\" />}\n action={props.action}\n content={formatMessage({\n id: 'app.components.EmptyStateLayout.content-document',\n defaultMessage: 'No content found',\n })}\n {...props}\n />\n </Box>\n </Flex>\n </PageMain>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Protect\n * -----------------------------------------------------------------------------------------------*/\nexport interface ProtectProps {\n /**\n * The children to render if the user has the required permissions.\n * If providing a function, it will be called with an object containing\n * the permissions the user has based on the array you passed to the component.\n */\n children: React.ReactNode | ((args: { permissions: Permission[] }) => React.ReactNode);\n /**\n * The permissions the user needs to have to access the content.\n */\n permissions?: Array<Omit<Partial<Permission>, 'action'> & Pick<Permission, 'action'>>;\n}\n\n/**\n * @public\n * @description A wrapper component that should be used to protect a page. It will check the permissions\n * you pass to it and render the children if any of the user's matching permissions grants access. If none do,\n * it renders the NoPermissions component. Whilst these checks happen it will render the loading component\n * and should the check fail it will render the error component with a notification.\n */\nconst Protect = ({ permissions = [], children }: ProtectProps) => {\n const userPermissions = useAuth('Protect', (state) => state.permissions);\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const matchingPermissions = (userPermissions || []).filter(\n (permission) =>\n permissions.findIndex(\n (perm) => perm.action === permission.action && perm.subject === permission.subject\n ) >= 0\n );\n\n const hasConditions = (permission: Permission) =>\n Array.isArray(permission.conditions) && permission.conditions.length > 0;\n\n const shouldCheckConditions = matchingPermissions.some(hasConditions);\n\n const { isLoading, error, data } = useCheckPermissionsQuery(\n {\n permissions: matchingPermissions.map((perm) => ({\n action: perm.action,\n subject: perm.subject,\n })),\n },\n {\n skip: !shouldCheckConditions,\n }\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 if (isLoading) {\n return <Loading />;\n }\n\n if (error) {\n return <Error />;\n }\n\n const { data: permissionsData } = data || {};\n\n const hasUnconditionedPermission = matchingPermissions.some(\n (permission) => !hasConditions(permission)\n );\n\n const canAccess =\n hasUnconditionedPermission || (permissionsData ?? []).some((perm) => perm === true);\n\n if (!canAccess) {\n return <NoPermissions />;\n }\n\n return (\n <>\n {typeof children === 'function' ? children({ permissions: matchingPermissions }) : children}\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Title\n * -----------------------------------------------------------------------------------------------*/\nexport interface TitleProps {\n children: string;\n}\n\n/**\n * @public\n * @description This component takes the children (must be a string) and sets\n * it as the title of the html.\n */\nconst Title = ({ children: title }: TitleProps) => {\n React.useEffect(() => {\n document.title = `${title} | Strapi`;\n }, [title]);\n\n return null;\n};\n\nconst Page = {\n Error,\n Loading,\n NoPermissions,\n Protect,\n NoData,\n Main: PageMain,\n Title,\n};\n\nexport { Page };\nexport type { ErrorProps, LoadingProps, NoPermissionsProps, PageMainProps as MainProps };\n"],"names":["PageMain","children","restProps","_jsx","Main","Loading","height","aria-busy","Flex","alignItems","justifyContent","Loader","Error","props","formatMessage","useIntl","EmptyStateLayout","icon","WarningCircle","width","content","id","defaultMessage","NoPermissions","Box","minWidth","EmptyPermissions","NoData","background","EmptyDocuments","action","Protect","permissions","userPermissions","useAuth","state","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","matchingPermissions","filter","permission","findIndex","perm","subject","hasConditions","Array","isArray","conditions","length","shouldCheckConditions","some","isLoading","error","data","useCheckPermissionsQuery","map","skip","React","useEffect","type","message","permissionsData","hasUnconditionedPermission","canAccess","_Fragment","Title","title","document","Page"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ var admin = require('../../services/admin.js');
|
|
|
8
8
|
var retryDynamicImport = require('../../utils/retryDynamicImport.js');
|
|
9
9
|
var Login = require('./components/Login.js');
|
|
10
10
|
var constants = require('./constants.js');
|
|
11
|
+
var utils = require('./utils.js');
|
|
11
12
|
|
|
12
13
|
/* -------------------------------------------------------------------------------------------------
|
|
13
14
|
* AuthPage
|
|
@@ -28,7 +29,7 @@ var constants = require('./constants.js');
|
|
|
28
29
|
defaultValue: constants.FORMS
|
|
29
30
|
});
|
|
30
31
|
const { token } = Auth.useAuth('AuthPage', (auth)=>auth);
|
|
31
|
-
if (!authType || !forms) {
|
|
32
|
+
if (!constants.isAuthType(authType) || !forms) {
|
|
32
33
|
return /*#__PURE__*/ jsxRuntime.jsx(reactRouterDom.Navigate, {
|
|
33
34
|
to: "/"
|
|
34
35
|
});
|
|
@@ -42,32 +43,36 @@ var constants = require('./constants.js');
|
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
45
|
// User is already logged in
|
|
45
|
-
if (authType !==
|
|
46
|
+
if (authType !== constants.AUTH_TYPES.REGISTER_ADMIN && authType !== constants.AUTH_TYPES.REGISTER && token) {
|
|
47
|
+
// Honour the `?redirectTo` the user was sent here with, otherwise logging in from a
|
|
48
|
+
// deep link always lands on the home page. `login()` sets the token before the login
|
|
49
|
+
// form gets to navigate, so this branch is what actually performs the redirect.
|
|
50
|
+
// See https://github.com/strapi/strapi/issues/19557
|
|
46
51
|
return /*#__PURE__*/ jsxRuntime.jsx(reactRouterDom.Navigate, {
|
|
47
|
-
to:
|
|
52
|
+
to: utils.getRedirectTo(search)
|
|
48
53
|
});
|
|
49
54
|
}
|
|
50
55
|
// there is already an admin user oo
|
|
51
|
-
if (hasAdmin && authType ===
|
|
56
|
+
if (hasAdmin && authType === constants.AUTH_TYPES.REGISTER_ADMIN && token) {
|
|
52
57
|
return /*#__PURE__*/ jsxRuntime.jsx(reactRouterDom.Navigate, {
|
|
53
|
-
to:
|
|
58
|
+
to: utils.getRedirectTo(search)
|
|
54
59
|
});
|
|
55
60
|
}
|
|
56
61
|
// Redirect the user to the register-admin if it is the first user
|
|
57
|
-
if (!hasAdmin && authType !==
|
|
62
|
+
if (!hasAdmin && authType !== constants.AUTH_TYPES.REGISTER_ADMIN) {
|
|
58
63
|
return /*#__PURE__*/ jsxRuntime.jsx(reactRouterDom.Navigate, {
|
|
59
64
|
to: {
|
|
60
|
-
pathname:
|
|
65
|
+
pathname: `/auth/${constants.AUTH_TYPES.REGISTER_ADMIN}`,
|
|
61
66
|
// Forward the `?redirectTo` from /auth/login
|
|
62
67
|
// /abc => /auth/login?redirectTo=%2Fabc => /auth/register-admin?redirectTo=%2Fabc
|
|
63
68
|
search
|
|
64
69
|
}
|
|
65
70
|
});
|
|
66
71
|
}
|
|
67
|
-
if (Login$1 && authType ===
|
|
72
|
+
if (Login$1 && authType === constants.AUTH_TYPES.LOGIN) {
|
|
68
73
|
// Assign the component to render for the login form
|
|
69
74
|
return /*#__PURE__*/ jsxRuntime.jsx(Login$1, {});
|
|
70
|
-
} else if (authType ===
|
|
75
|
+
} else if (authType === constants.AUTH_TYPES.LOGIN && !Login$1) {
|
|
71
76
|
// block rendering until the Login EE component is fully loaded
|
|
72
77
|
return null;
|
|
73
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthPage.js","sources":["../../../../../../admin/src/pages/Auth/AuthPage.tsx"],"sourcesContent":["import { Navigate, useLocation, useMatch } from 'react-router-dom';\n\nimport { useAuth } from '../../features/Auth';\nimport { useEnterprise } from '../../hooks/useEnterprise';\nimport { useInitQuery } from '../../services/admin';\nimport { retryDynamicImport } from '../../utils/retryDynamicImport';\n\nimport { Login as LoginCE } from './components/Login';\nimport { FORMS, FormDictionary } from './constants';\n\n/* -------------------------------------------------------------------------------------------------\n * AuthPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst AuthPage = () => {\n const { search } = useLocation();\n const match = useMatch('/auth/:authType');\n const authType = match?.params.authType;\n const { data } = useInitQuery();\n const { hasAdmin } = data ?? {};\n const Login = useEnterprise(\n LoginCE,\n async () =>\n (\n await retryDynamicImport(\n () => import('../../../../ee/admin/src/pages/AuthPage/components/Login')\n )\n ).LoginEE\n );\n const forms = useEnterprise<FormDictionary, Partial<FormDictionary>>(\n FORMS,\n async () =>\n (await retryDynamicImport(() => import('../../../../ee/admin/src/pages/AuthPage/constants')))\n .FORMS,\n {\n combine(ceForms, eeForms) {\n return {\n ...ceForms,\n ...eeForms,\n };\n },\n defaultValue: FORMS,\n }\n );\n\n const { token } = useAuth('AuthPage', (auth) => auth);\n\n if (!authType || !forms) {\n return <Navigate to=\"/\" />;\n }\n\n const Component = forms[authType
|
|
1
|
+
{"version":3,"file":"AuthPage.js","sources":["../../../../../../admin/src/pages/Auth/AuthPage.tsx"],"sourcesContent":["import { Navigate, useLocation, useMatch } from 'react-router-dom';\n\nimport { useAuth } from '../../features/Auth';\nimport { useEnterprise } from '../../hooks/useEnterprise';\nimport { useInitQuery } from '../../services/admin';\nimport { retryDynamicImport } from '../../utils/retryDynamicImport';\n\nimport { Login as LoginCE } from './components/Login';\nimport { AUTH_TYPES, FORMS, FormDictionary, isAuthType } from './constants';\nimport { getRedirectTo } from './utils';\n\n/* -------------------------------------------------------------------------------------------------\n * AuthPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst AuthPage = () => {\n const { search } = useLocation();\n const match = useMatch('/auth/:authType');\n const authType = match?.params.authType;\n const { data } = useInitQuery();\n const { hasAdmin } = data ?? {};\n const Login = useEnterprise(\n LoginCE,\n async () =>\n (\n await retryDynamicImport(\n () => import('../../../../ee/admin/src/pages/AuthPage/components/Login')\n )\n ).LoginEE\n );\n const forms = useEnterprise<FormDictionary, Partial<FormDictionary>>(\n FORMS,\n async () =>\n (await retryDynamicImport(() => import('../../../../ee/admin/src/pages/AuthPage/constants')))\n .FORMS,\n {\n combine(ceForms, eeForms) {\n return {\n ...ceForms,\n ...eeForms,\n };\n },\n defaultValue: FORMS,\n }\n );\n\n const { token } = useAuth('AuthPage', (auth) => auth);\n\n if (!isAuthType(authType) || !forms) {\n return <Navigate to=\"/\" />;\n }\n\n const Component = forms[authType];\n\n // Redirect the user to the login page if\n // the endpoint does not exists\n if (!Component) {\n return <Navigate to=\"/\" />;\n }\n\n // User is already logged in\n if (authType !== AUTH_TYPES.REGISTER_ADMIN && authType !== AUTH_TYPES.REGISTER && token) {\n // Honour the `?redirectTo` the user was sent here with, otherwise logging in from a\n // deep link always lands on the home page. `login()` sets the token before the login\n // form gets to navigate, so this branch is what actually performs the redirect.\n // See https://github.com/strapi/strapi/issues/19557\n return <Navigate to={getRedirectTo(search)} />;\n }\n\n // there is already an admin user oo\n if (hasAdmin && authType === AUTH_TYPES.REGISTER_ADMIN && token) {\n return <Navigate to={getRedirectTo(search)} />;\n }\n\n // Redirect the user to the register-admin if it is the first user\n if (!hasAdmin && authType !== AUTH_TYPES.REGISTER_ADMIN) {\n return (\n <Navigate\n to={{\n pathname: `/auth/${AUTH_TYPES.REGISTER_ADMIN}`,\n // Forward the `?redirectTo` from /auth/login\n // /abc => /auth/login?redirectTo=%2Fabc => /auth/register-admin?redirectTo=%2Fabc\n search,\n }}\n />\n );\n }\n\n if (Login && authType === AUTH_TYPES.LOGIN) {\n // Assign the component to render for the login form\n return <Login />;\n } else if (authType === AUTH_TYPES.LOGIN && !Login) {\n // block rendering until the Login EE component is fully loaded\n return null;\n }\n\n return <Component hasAdmin={hasAdmin} />;\n};\n\nexport { AuthPage };\n"],"names":["AuthPage","search","useLocation","match","useMatch","authType","params","data","useInitQuery","hasAdmin","Login","useEnterprise","LoginCE","retryDynamicImport","LoginEE","forms","FORMS","combine","ceForms","eeForms","defaultValue","token","useAuth","auth","isAuthType","_jsx","Navigate","to","Component","AUTH_TYPES","REGISTER_ADMIN","REGISTER","getRedirectTo","pathname","LOGIN"],"mappings":";;;;;;;;;;;;AAWA;;AAEkG,2GAE5FA,QAAAA,GAAW,IAAA;IACf,MAAM,EAAEC,MAAM,EAAE,GAAGC,0BAAAA,EAAAA;AACnB,IAAA,MAAMC,QAAQC,uBAAAA,CAAS,iBAAA,CAAA;IACvB,MAAMC,QAAAA,GAAWF,OAAOG,MAAAA,CAAOD,QAAAA;IAC/B,MAAM,EAAEE,IAAI,EAAE,GAAGC,kBAAAA,EAAAA;AACjB,IAAA,MAAM,EAAEC,QAAQ,EAAE,GAAGF,QAAQ,EAAC;AAC9B,IAAA,MAAMG,OAAAA,GAAQC,2BAAAA,CACZC,WAAAA,EACA,UACE,CACE,MAAMC,qCAAAA,CACJ,IAAM,oDAAO,6DAAA,KAAA,CACf,EACAC,OAAO,CAAA;AAEb,IAAA,MAAMC,KAAAA,GAAQJ,2BAAAA,CACZK,eAAAA,EACA,UACE,CAAC,MAAMH,qCAAAA,CAAmB,IAAM,oDAAO,sDAAA,KAAA,CAAoD,EACxFG,KAAK,EACV;QACEC,OAAAA,CAAAA,CAAQC,OAAO,EAAEC,OAAO,EAAA;YACtB,OAAO;AACL,gBAAA,GAAGD,OAAO;AACV,gBAAA,GAAGC;AACL,aAAA;AACF,QAAA,CAAA;QACAC,YAAAA,EAAcJ;AAChB,KAAA,CAAA;AAGF,IAAA,MAAM,EAAEK,KAAK,EAAE,GAAGC,YAAAA,CAAQ,UAAA,EAAY,CAACC,IAAAA,GAASA,IAAAA,CAAAA;AAEhD,IAAA,IAAI,CAACC,oBAAAA,CAAWnB,QAAAA,CAAAA,IAAa,CAACU,KAAAA,EAAO;AACnC,QAAA,qBAAOU,cAAA,CAACC,uBAAAA,EAAAA;YAASC,EAAAA,EAAG;;AACtB,IAAA;IAEA,MAAMC,SAAAA,GAAYb,KAAK,CAACV,QAAAA,CAAS;;;AAIjC,IAAA,IAAI,CAACuB,SAAAA,EAAW;AACd,QAAA,qBAAOH,cAAA,CAACC,uBAAAA,EAAAA;YAASC,EAAAA,EAAG;;AACtB,IAAA;;IAGA,IAAItB,QAAAA,KAAawB,qBAAWC,cAAc,IAAIzB,aAAawB,oBAAAA,CAAWE,QAAQ,IAAIV,KAAAA,EAAO;;;;;AAKvF,QAAA,qBAAOI,cAAA,CAACC,uBAAAA,EAAAA;AAASC,YAAAA,EAAAA,EAAIK,mBAAAA,CAAc/B,MAAAA;;AACrC,IAAA;;AAGA,IAAA,IAAIQ,QAAAA,IAAYJ,QAAAA,KAAawB,oBAAAA,CAAWC,cAAc,IAAIT,KAAAA,EAAO;AAC/D,QAAA,qBAAOI,cAAA,CAACC,uBAAAA,EAAAA;AAASC,YAAAA,EAAAA,EAAIK,mBAAAA,CAAc/B,MAAAA;;AACrC,IAAA;;AAGA,IAAA,IAAI,CAACQ,QAAAA,IAAYJ,QAAAA,KAAawB,oBAAAA,CAAWC,cAAc,EAAE;AACvD,QAAA,qBACEL,cAAA,CAACC,uBAAAA,EAAAA;YACCC,EAAAA,EAAI;AACFM,gBAAAA,QAAAA,EAAU,CAAC,MAAM,EAAEJ,oBAAAA,CAAWC,cAAc,CAAA,CAAE;;;AAG9C7B,gBAAAA;AACF;;AAGN,IAAA;AAEA,IAAA,IAAIS,OAAAA,IAASL,QAAAA,KAAawB,oBAAAA,CAAWK,KAAK,EAAE;;AAE1C,QAAA,qBAAOT,cAAA,CAACf,OAAAA,EAAAA,EAAAA,CAAAA;AACV,IAAA,CAAA,MAAO,IAAIL,QAAAA,KAAawB,oBAAAA,CAAWK,KAAK,IAAI,CAACxB,OAAAA,EAAO;;QAElD,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,qBAAOe,cAAA,CAACG,SAAAA,EAAAA;QAAUnB,QAAAA,EAAUA;;AAC9B;;;;"}
|
|
@@ -5,7 +5,8 @@ import { useEnterprise } from '../../hooks/useEnterprise.mjs';
|
|
|
5
5
|
import { useInitQuery } from '../../services/admin.mjs';
|
|
6
6
|
import { retryDynamicImport } from '../../utils/retryDynamicImport.mjs';
|
|
7
7
|
import { Login } from './components/Login.mjs';
|
|
8
|
-
import { FORMS } from './constants.mjs';
|
|
8
|
+
import { FORMS, isAuthType, AUTH_TYPES } from './constants.mjs';
|
|
9
|
+
import { getRedirectTo } from './utils.mjs';
|
|
9
10
|
|
|
10
11
|
/* -------------------------------------------------------------------------------------------------
|
|
11
12
|
* AuthPage
|
|
@@ -26,7 +27,7 @@ import { FORMS } from './constants.mjs';
|
|
|
26
27
|
defaultValue: FORMS
|
|
27
28
|
});
|
|
28
29
|
const { token } = useAuth('AuthPage', (auth)=>auth);
|
|
29
|
-
if (!authType || !forms) {
|
|
30
|
+
if (!isAuthType(authType) || !forms) {
|
|
30
31
|
return /*#__PURE__*/ jsx(Navigate, {
|
|
31
32
|
to: "/"
|
|
32
33
|
});
|
|
@@ -40,32 +41,36 @@ import { FORMS } from './constants.mjs';
|
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
43
|
// User is already logged in
|
|
43
|
-
if (authType !==
|
|
44
|
+
if (authType !== AUTH_TYPES.REGISTER_ADMIN && authType !== AUTH_TYPES.REGISTER && token) {
|
|
45
|
+
// Honour the `?redirectTo` the user was sent here with, otherwise logging in from a
|
|
46
|
+
// deep link always lands on the home page. `login()` sets the token before the login
|
|
47
|
+
// form gets to navigate, so this branch is what actually performs the redirect.
|
|
48
|
+
// See https://github.com/strapi/strapi/issues/19557
|
|
44
49
|
return /*#__PURE__*/ jsx(Navigate, {
|
|
45
|
-
to:
|
|
50
|
+
to: getRedirectTo(search)
|
|
46
51
|
});
|
|
47
52
|
}
|
|
48
53
|
// there is already an admin user oo
|
|
49
|
-
if (hasAdmin && authType ===
|
|
54
|
+
if (hasAdmin && authType === AUTH_TYPES.REGISTER_ADMIN && token) {
|
|
50
55
|
return /*#__PURE__*/ jsx(Navigate, {
|
|
51
|
-
to:
|
|
56
|
+
to: getRedirectTo(search)
|
|
52
57
|
});
|
|
53
58
|
}
|
|
54
59
|
// Redirect the user to the register-admin if it is the first user
|
|
55
|
-
if (!hasAdmin && authType !==
|
|
60
|
+
if (!hasAdmin && authType !== AUTH_TYPES.REGISTER_ADMIN) {
|
|
56
61
|
return /*#__PURE__*/ jsx(Navigate, {
|
|
57
62
|
to: {
|
|
58
|
-
pathname:
|
|
63
|
+
pathname: `/auth/${AUTH_TYPES.REGISTER_ADMIN}`,
|
|
59
64
|
// Forward the `?redirectTo` from /auth/login
|
|
60
65
|
// /abc => /auth/login?redirectTo=%2Fabc => /auth/register-admin?redirectTo=%2Fabc
|
|
61
66
|
search
|
|
62
67
|
}
|
|
63
68
|
});
|
|
64
69
|
}
|
|
65
|
-
if (Login$1 && authType ===
|
|
70
|
+
if (Login$1 && authType === AUTH_TYPES.LOGIN) {
|
|
66
71
|
// Assign the component to render for the login form
|
|
67
72
|
return /*#__PURE__*/ jsx(Login$1, {});
|
|
68
|
-
} else if (authType ===
|
|
73
|
+
} else if (authType === AUTH_TYPES.LOGIN && !Login$1) {
|
|
69
74
|
// block rendering until the Login EE component is fully loaded
|
|
70
75
|
return null;
|
|
71
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthPage.mjs","sources":["../../../../../../admin/src/pages/Auth/AuthPage.tsx"],"sourcesContent":["import { Navigate, useLocation, useMatch } from 'react-router-dom';\n\nimport { useAuth } from '../../features/Auth';\nimport { useEnterprise } from '../../hooks/useEnterprise';\nimport { useInitQuery } from '../../services/admin';\nimport { retryDynamicImport } from '../../utils/retryDynamicImport';\n\nimport { Login as LoginCE } from './components/Login';\nimport { FORMS, FormDictionary } from './constants';\n\n/* -------------------------------------------------------------------------------------------------\n * AuthPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst AuthPage = () => {\n const { search } = useLocation();\n const match = useMatch('/auth/:authType');\n const authType = match?.params.authType;\n const { data } = useInitQuery();\n const { hasAdmin } = data ?? {};\n const Login = useEnterprise(\n LoginCE,\n async () =>\n (\n await retryDynamicImport(\n () => import('../../../../ee/admin/src/pages/AuthPage/components/Login')\n )\n ).LoginEE\n );\n const forms = useEnterprise<FormDictionary, Partial<FormDictionary>>(\n FORMS,\n async () =>\n (await retryDynamicImport(() => import('../../../../ee/admin/src/pages/AuthPage/constants')))\n .FORMS,\n {\n combine(ceForms, eeForms) {\n return {\n ...ceForms,\n ...eeForms,\n };\n },\n defaultValue: FORMS,\n }\n );\n\n const { token } = useAuth('AuthPage', (auth) => auth);\n\n if (!authType || !forms) {\n return <Navigate to=\"/\" />;\n }\n\n const Component = forms[authType
|
|
1
|
+
{"version":3,"file":"AuthPage.mjs","sources":["../../../../../../admin/src/pages/Auth/AuthPage.tsx"],"sourcesContent":["import { Navigate, useLocation, useMatch } from 'react-router-dom';\n\nimport { useAuth } from '../../features/Auth';\nimport { useEnterprise } from '../../hooks/useEnterprise';\nimport { useInitQuery } from '../../services/admin';\nimport { retryDynamicImport } from '../../utils/retryDynamicImport';\n\nimport { Login as LoginCE } from './components/Login';\nimport { AUTH_TYPES, FORMS, FormDictionary, isAuthType } from './constants';\nimport { getRedirectTo } from './utils';\n\n/* -------------------------------------------------------------------------------------------------\n * AuthPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst AuthPage = () => {\n const { search } = useLocation();\n const match = useMatch('/auth/:authType');\n const authType = match?.params.authType;\n const { data } = useInitQuery();\n const { hasAdmin } = data ?? {};\n const Login = useEnterprise(\n LoginCE,\n async () =>\n (\n await retryDynamicImport(\n () => import('../../../../ee/admin/src/pages/AuthPage/components/Login')\n )\n ).LoginEE\n );\n const forms = useEnterprise<FormDictionary, Partial<FormDictionary>>(\n FORMS,\n async () =>\n (await retryDynamicImport(() => import('../../../../ee/admin/src/pages/AuthPage/constants')))\n .FORMS,\n {\n combine(ceForms, eeForms) {\n return {\n ...ceForms,\n ...eeForms,\n };\n },\n defaultValue: FORMS,\n }\n );\n\n const { token } = useAuth('AuthPage', (auth) => auth);\n\n if (!isAuthType(authType) || !forms) {\n return <Navigate to=\"/\" />;\n }\n\n const Component = forms[authType];\n\n // Redirect the user to the login page if\n // the endpoint does not exists\n if (!Component) {\n return <Navigate to=\"/\" />;\n }\n\n // User is already logged in\n if (authType !== AUTH_TYPES.REGISTER_ADMIN && authType !== AUTH_TYPES.REGISTER && token) {\n // Honour the `?redirectTo` the user was sent here with, otherwise logging in from a\n // deep link always lands on the home page. `login()` sets the token before the login\n // form gets to navigate, so this branch is what actually performs the redirect.\n // See https://github.com/strapi/strapi/issues/19557\n return <Navigate to={getRedirectTo(search)} />;\n }\n\n // there is already an admin user oo\n if (hasAdmin && authType === AUTH_TYPES.REGISTER_ADMIN && token) {\n return <Navigate to={getRedirectTo(search)} />;\n }\n\n // Redirect the user to the register-admin if it is the first user\n if (!hasAdmin && authType !== AUTH_TYPES.REGISTER_ADMIN) {\n return (\n <Navigate\n to={{\n pathname: `/auth/${AUTH_TYPES.REGISTER_ADMIN}`,\n // Forward the `?redirectTo` from /auth/login\n // /abc => /auth/login?redirectTo=%2Fabc => /auth/register-admin?redirectTo=%2Fabc\n search,\n }}\n />\n );\n }\n\n if (Login && authType === AUTH_TYPES.LOGIN) {\n // Assign the component to render for the login form\n return <Login />;\n } else if (authType === AUTH_TYPES.LOGIN && !Login) {\n // block rendering until the Login EE component is fully loaded\n return null;\n }\n\n return <Component hasAdmin={hasAdmin} />;\n};\n\nexport { AuthPage };\n"],"names":["AuthPage","search","useLocation","match","useMatch","authType","params","data","useInitQuery","hasAdmin","Login","useEnterprise","LoginCE","retryDynamicImport","LoginEE","forms","FORMS","combine","ceForms","eeForms","defaultValue","token","useAuth","auth","isAuthType","_jsx","Navigate","to","Component","AUTH_TYPES","REGISTER_ADMIN","REGISTER","getRedirectTo","pathname","LOGIN"],"mappings":";;;;;;;;;;AAWA;;AAEkG,2GAE5FA,QAAAA,GAAW,IAAA;IACf,MAAM,EAAEC,MAAM,EAAE,GAAGC,WAAAA,EAAAA;AACnB,IAAA,MAAMC,QAAQC,QAAAA,CAAS,iBAAA,CAAA;IACvB,MAAMC,QAAAA,GAAWF,OAAOG,MAAAA,CAAOD,QAAAA;IAC/B,MAAM,EAAEE,IAAI,EAAE,GAAGC,YAAAA,EAAAA;AACjB,IAAA,MAAM,EAAEC,QAAQ,EAAE,GAAGF,QAAQ,EAAC;AAC9B,IAAA,MAAMG,OAAAA,GAAQC,aAAAA,CACZC,KAAAA,EACA,UACE,CACE,MAAMC,kBAAAA,CACJ,IAAM,OAAO,8DAAA,CAAA,CACf,EACAC,OAAO,CAAA;AAEb,IAAA,MAAMC,KAAAA,GAAQJ,aAAAA,CACZK,KAAAA,EACA,UACE,CAAC,MAAMH,kBAAAA,CAAmB,IAAM,OAAO,uDAAA,CAAA,CAAoD,EACxFG,KAAK,EACV;QACEC,OAAAA,CAAAA,CAAQC,OAAO,EAAEC,OAAO,EAAA;YACtB,OAAO;AACL,gBAAA,GAAGD,OAAO;AACV,gBAAA,GAAGC;AACL,aAAA;AACF,QAAA,CAAA;QACAC,YAAAA,EAAcJ;AAChB,KAAA,CAAA;AAGF,IAAA,MAAM,EAAEK,KAAK,EAAE,GAAGC,OAAAA,CAAQ,UAAA,EAAY,CAACC,IAAAA,GAASA,IAAAA,CAAAA;AAEhD,IAAA,IAAI,CAACC,UAAAA,CAAWnB,QAAAA,CAAAA,IAAa,CAACU,KAAAA,EAAO;AACnC,QAAA,qBAAOU,GAAA,CAACC,QAAAA,EAAAA;YAASC,EAAAA,EAAG;;AACtB,IAAA;IAEA,MAAMC,SAAAA,GAAYb,KAAK,CAACV,QAAAA,CAAS;;;AAIjC,IAAA,IAAI,CAACuB,SAAAA,EAAW;AACd,QAAA,qBAAOH,GAAA,CAACC,QAAAA,EAAAA;YAASC,EAAAA,EAAG;;AACtB,IAAA;;IAGA,IAAItB,QAAAA,KAAawB,WAAWC,cAAc,IAAIzB,aAAawB,UAAAA,CAAWE,QAAQ,IAAIV,KAAAA,EAAO;;;;;AAKvF,QAAA,qBAAOI,GAAA,CAACC,QAAAA,EAAAA;AAASC,YAAAA,EAAAA,EAAIK,aAAAA,CAAc/B,MAAAA;;AACrC,IAAA;;AAGA,IAAA,IAAIQ,QAAAA,IAAYJ,QAAAA,KAAawB,UAAAA,CAAWC,cAAc,IAAIT,KAAAA,EAAO;AAC/D,QAAA,qBAAOI,GAAA,CAACC,QAAAA,EAAAA;AAASC,YAAAA,EAAAA,EAAIK,aAAAA,CAAc/B,MAAAA;;AACrC,IAAA;;AAGA,IAAA,IAAI,CAACQ,QAAAA,IAAYJ,QAAAA,KAAawB,UAAAA,CAAWC,cAAc,EAAE;AACvD,QAAA,qBACEL,GAAA,CAACC,QAAAA,EAAAA;YACCC,EAAAA,EAAI;AACFM,gBAAAA,QAAAA,EAAU,CAAC,MAAM,EAAEJ,UAAAA,CAAWC,cAAc,CAAA,CAAE;;;AAG9C7B,gBAAAA;AACF;;AAGN,IAAA;AAEA,IAAA,IAAIS,OAAAA,IAASL,QAAAA,KAAawB,UAAAA,CAAWK,KAAK,EAAE;;AAE1C,QAAA,qBAAOT,GAAA,CAACf,OAAAA,EAAAA,EAAAA,CAAAA;AACV,IAAA,CAAA,MAAO,IAAIL,QAAAA,KAAawB,UAAAA,CAAWK,KAAK,IAAI,CAACxB,OAAAA,EAAO;;QAElD,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,qBAAOe,GAAA,CAACG,SAAAA,EAAAA;QAAUnB,QAAAA,EAAUA;;AAC9B;;;;"}
|
|
@@ -13,6 +13,7 @@ var UnauthenticatedLogo = require('../../../components/UnauthenticatedLogo.js');
|
|
|
13
13
|
var Auth = require('../../../features/Auth.js');
|
|
14
14
|
var UnauthenticatedLayout = require('../../../layouts/UnauthenticatedLayout.js');
|
|
15
15
|
var translatedErrors = require('../../../utils/translatedErrors.js');
|
|
16
|
+
var utils = require('../utils.js');
|
|
16
17
|
|
|
17
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
19
|
|
|
@@ -50,9 +51,6 @@ const Login = ({ children })=>{
|
|
|
50
51
|
const [apiError, setApiError] = React__namespace.useState();
|
|
51
52
|
const { formatMessage } = reactIntl.useIntl();
|
|
52
53
|
const { search: searchString } = reactRouterDom.useLocation();
|
|
53
|
-
const query = React__namespace.useMemo(()=>new URLSearchParams(searchString), [
|
|
54
|
-
searchString
|
|
55
|
-
]);
|
|
56
54
|
const navigate = reactRouterDom.useNavigate();
|
|
57
55
|
const { login } = Auth.useAuth('Login', (auth)=>auth);
|
|
58
56
|
const handleLogin = async (body)=>{
|
|
@@ -66,9 +64,7 @@ const Login = ({ children })=>{
|
|
|
66
64
|
}
|
|
67
65
|
setApiError(message);
|
|
68
66
|
} else {
|
|
69
|
-
|
|
70
|
-
const redirectUrl = redirectTo ? decodeURIComponent(redirectTo) : '/';
|
|
71
|
-
navigate(redirectUrl);
|
|
67
|
+
navigate(utils.getRedirectTo(searchString));
|
|
72
68
|
}
|
|
73
69
|
};
|
|
74
70
|
return /*#__PURE__*/ jsxRuntime.jsx(UnauthenticatedLayout.UnauthenticatedLayout, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Login.js","sources":["../../../../../../../admin/src/pages/Auth/components/Login.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Main, Typography, Link } from '@strapi/design-system';\nimport camelCase from 'lodash/camelCase';\nimport { useIntl } from 'react-intl';\nimport { NavLink, useLocation, useNavigate } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { Form } from '../../../components/Form';\nimport { InputRenderer } from '../../../components/FormInputs/Renderer';\nimport { Logo } from '../../../components/UnauthenticatedLogo';\nimport { useAuth } from '../../../features/Auth';\nimport {\n UnauthenticatedLayout,\n Column,\n LayoutContent,\n} from '../../../layouts/UnauthenticatedLayout';\nimport { translatedErrors } from '../../../utils/translatedErrors';\n\nimport type { Login } from '../../../../../shared/contracts/authentication';\n\ninterface LoginProps {\n children?: React.ReactNode;\n}\n\nconst LOGIN_SCHEMA = yup.object().shape({\n email: yup\n .string()\n .nullable()\n .email({\n id: translatedErrors.email.id,\n defaultMessage: 'Not a valid email',\n })\n .required(translatedErrors.required),\n password: yup.string().required(translatedErrors.required).nullable(),\n rememberMe: yup.bool().nullable(),\n});\n\nconst Login = ({ children }: LoginProps) => {\n const [apiError, setApiError] = React.useState<string>();\n const { formatMessage } = useIntl();\n const { search: searchString } = useLocation();\n const query = React.useMemo(() => new URLSearchParams(searchString), [searchString]);\n const navigate = useNavigate();\n\n const { login } = useAuth('Login', (auth) => auth);\n\n const handleLogin = async (body: Parameters<typeof login>[0]) => {\n setApiError(undefined);\n\n const res = await login(body);\n\n if ('error' in res) {\n const message = res.error.message ?? 'Something went wrong';\n\n if (camelCase(message).toLowerCase() === 'usernotactive') {\n navigate('/auth/oops');\n return;\n }\n\n setApiError(message);\n } else {\n const redirectTo = query.get('redirectTo');\n const redirectUrl = redirectTo ? decodeURIComponent(redirectTo) : '/';\n\n navigate(redirectUrl);\n }\n };\n\n return (\n <UnauthenticatedLayout>\n <Main>\n <LayoutContent>\n <Column>\n <Logo />\n <Box paddingTop={6} paddingBottom={1}>\n <Typography variant=\"alpha\" tag=\"h1\" textAlign=\"center\">\n {formatMessage({\n id: 'Auth.form.welcome.title',\n defaultMessage: 'Welcome!',\n })}\n </Typography>\n </Box>\n <Box paddingBottom={7}>\n <Typography\n variant=\"epsilon\"\n textColor=\"neutral600\"\n textAlign=\"center\"\n display=\"block\"\n >\n {formatMessage({\n id: 'Auth.form.welcome.subtitle',\n defaultMessage: 'Log in to your Strapi account',\n })}\n </Typography>\n </Box>\n {apiError ? (\n <Typography id=\"global-form-error\" role=\"alert\" tabIndex={-1} textColor=\"danger600\">\n {apiError}\n </Typography>\n ) : null}\n </Column>\n <Form\n method=\"PUT\"\n initialValues={{\n email: '',\n password: '',\n rememberMe: false,\n }}\n onSubmit={(values) => {\n handleLogin(values);\n }}\n validationSchema={LOGIN_SCHEMA}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {[\n {\n label: formatMessage({ id: 'Auth.form.email.label', defaultMessage: 'Email' }),\n name: 'email',\n placeholder: formatMessage({\n id: 'Auth.form.email.placeholder',\n defaultMessage: 'kai@doe.com',\n }),\n required: true,\n type: 'email' as const,\n },\n {\n label: formatMessage({\n id: 'global.password',\n defaultMessage: 'Password',\n }),\n name: 'password',\n required: true,\n type: 'password' as const,\n },\n {\n label: formatMessage({\n id: 'Auth.form.rememberMe.label',\n defaultMessage: 'Remember me',\n }),\n name: 'rememberMe',\n type: 'checkbox' as const,\n },\n ].map((field) => (\n <InputRenderer key={field.name} {...field} />\n ))}\n <Button fullWidth type=\"submit\">\n {formatMessage({ id: 'Auth.form.button.login', defaultMessage: 'Login' })}\n </Button>\n </Flex>\n </Form>\n {children}\n </LayoutContent>\n <Flex justifyContent=\"center\">\n <Box paddingTop={4}>\n <Link isExternal={false} tag={NavLink} to=\"/auth/forgot-password\">\n {formatMessage({\n id: 'Auth.link.forgot-password',\n defaultMessage: 'Forgot your password?',\n })}\n </Link>\n </Box>\n </Flex>\n </Main>\n </UnauthenticatedLayout>\n );\n};\n\nexport { Login };\nexport type { LoginProps };\n"],"names":["LOGIN_SCHEMA","yup","object","shape","email","string","nullable","id","translatedErrors","defaultMessage","required","password","rememberMe","bool","Login","children","apiError","setApiError","React","useState","formatMessage","useIntl","search","searchString","useLocation","query","useMemo","URLSearchParams","navigate","useNavigate","login","useAuth","auth","handleLogin","body","undefined","res","message","error","camelCase","toLowerCase","redirectTo","get","redirectUrl","decodeURIComponent","_jsx","UnauthenticatedLayout","_jsxs","Main","LayoutContent","Column","Logo","Box","paddingTop","paddingBottom","Typography","variant","tag","textAlign","textColor","display","role","tabIndex","Form","method","initialValues","onSubmit","values","validationSchema","Flex","direction","alignItems","gap","label","name","placeholder","type","map","field","InputRenderer","Button","fullWidth","justifyContent","Link","isExternal","NavLink","to"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Login.js","sources":["../../../../../../../admin/src/pages/Auth/components/Login.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Main, Typography, Link } from '@strapi/design-system';\nimport camelCase from 'lodash/camelCase';\nimport { useIntl } from 'react-intl';\nimport { NavLink, useLocation, useNavigate } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { Form } from '../../../components/Form';\nimport { InputRenderer } from '../../../components/FormInputs/Renderer';\nimport { Logo } from '../../../components/UnauthenticatedLogo';\nimport { useAuth } from '../../../features/Auth';\nimport {\n UnauthenticatedLayout,\n Column,\n LayoutContent,\n} from '../../../layouts/UnauthenticatedLayout';\nimport { translatedErrors } from '../../../utils/translatedErrors';\nimport { getRedirectTo } from '../utils';\n\nimport type { Login } from '../../../../../shared/contracts/authentication';\n\ninterface LoginProps {\n children?: React.ReactNode;\n}\n\nconst LOGIN_SCHEMA = yup.object().shape({\n email: yup\n .string()\n .nullable()\n .email({\n id: translatedErrors.email.id,\n defaultMessage: 'Not a valid email',\n })\n .required(translatedErrors.required),\n password: yup.string().required(translatedErrors.required).nullable(),\n rememberMe: yup.bool().nullable(),\n});\n\nconst Login = ({ children }: LoginProps) => {\n const [apiError, setApiError] = React.useState<string>();\n const { formatMessage } = useIntl();\n const { search: searchString } = useLocation();\n const navigate = useNavigate();\n\n const { login } = useAuth('Login', (auth) => auth);\n\n const handleLogin = async (body: Parameters<typeof login>[0]) => {\n setApiError(undefined);\n\n const res = await login(body);\n\n if ('error' in res) {\n const message = res.error.message ?? 'Something went wrong';\n\n if (camelCase(message).toLowerCase() === 'usernotactive') {\n navigate('/auth/oops');\n return;\n }\n\n setApiError(message);\n } else {\n navigate(getRedirectTo(searchString));\n }\n };\n\n return (\n <UnauthenticatedLayout>\n <Main>\n <LayoutContent>\n <Column>\n <Logo />\n <Box paddingTop={6} paddingBottom={1}>\n <Typography variant=\"alpha\" tag=\"h1\" textAlign=\"center\">\n {formatMessage({\n id: 'Auth.form.welcome.title',\n defaultMessage: 'Welcome!',\n })}\n </Typography>\n </Box>\n <Box paddingBottom={7}>\n <Typography\n variant=\"epsilon\"\n textColor=\"neutral600\"\n textAlign=\"center\"\n display=\"block\"\n >\n {formatMessage({\n id: 'Auth.form.welcome.subtitle',\n defaultMessage: 'Log in to your Strapi account',\n })}\n </Typography>\n </Box>\n {apiError ? (\n <Typography id=\"global-form-error\" role=\"alert\" tabIndex={-1} textColor=\"danger600\">\n {apiError}\n </Typography>\n ) : null}\n </Column>\n <Form\n method=\"PUT\"\n initialValues={{\n email: '',\n password: '',\n rememberMe: false,\n }}\n onSubmit={(values) => {\n handleLogin(values);\n }}\n validationSchema={LOGIN_SCHEMA}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {[\n {\n label: formatMessage({ id: 'Auth.form.email.label', defaultMessage: 'Email' }),\n name: 'email',\n placeholder: formatMessage({\n id: 'Auth.form.email.placeholder',\n defaultMessage: 'kai@doe.com',\n }),\n required: true,\n type: 'email' as const,\n },\n {\n label: formatMessage({\n id: 'global.password',\n defaultMessage: 'Password',\n }),\n name: 'password',\n required: true,\n type: 'password' as const,\n },\n {\n label: formatMessage({\n id: 'Auth.form.rememberMe.label',\n defaultMessage: 'Remember me',\n }),\n name: 'rememberMe',\n type: 'checkbox' as const,\n },\n ].map((field) => (\n <InputRenderer key={field.name} {...field} />\n ))}\n <Button fullWidth type=\"submit\">\n {formatMessage({ id: 'Auth.form.button.login', defaultMessage: 'Login' })}\n </Button>\n </Flex>\n </Form>\n {children}\n </LayoutContent>\n <Flex justifyContent=\"center\">\n <Box paddingTop={4}>\n <Link isExternal={false} tag={NavLink} to=\"/auth/forgot-password\">\n {formatMessage({\n id: 'Auth.link.forgot-password',\n defaultMessage: 'Forgot your password?',\n })}\n </Link>\n </Box>\n </Flex>\n </Main>\n </UnauthenticatedLayout>\n );\n};\n\nexport { Login };\nexport type { LoginProps };\n"],"names":["LOGIN_SCHEMA","yup","object","shape","email","string","nullable","id","translatedErrors","defaultMessage","required","password","rememberMe","bool","Login","children","apiError","setApiError","React","useState","formatMessage","useIntl","search","searchString","useLocation","navigate","useNavigate","login","useAuth","auth","handleLogin","body","undefined","res","message","error","camelCase","toLowerCase","getRedirectTo","_jsx","UnauthenticatedLayout","_jsxs","Main","LayoutContent","Column","Logo","Box","paddingTop","paddingBottom","Typography","variant","tag","textAlign","textColor","display","role","tabIndex","Form","method","initialValues","onSubmit","values","validationSchema","Flex","direction","alignItems","gap","label","name","placeholder","type","map","field","InputRenderer","Button","fullWidth","justifyContent","Link","isExternal","NavLink","to"],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ import { Logo } from '../../../components/UnauthenticatedLogo.mjs';
|
|
|
11
11
|
import { useAuth } from '../../../features/Auth.mjs';
|
|
12
12
|
import { UnauthenticatedLayout, LayoutContent, Column } from '../../../layouts/UnauthenticatedLayout.mjs';
|
|
13
13
|
import { translatedErrors as errorsTrads } from '../../../utils/translatedErrors.mjs';
|
|
14
|
+
import { getRedirectTo } from '../utils.mjs';
|
|
14
15
|
|
|
15
16
|
const LOGIN_SCHEMA = yup.object().shape({
|
|
16
17
|
email: yup.string().nullable().email({
|
|
@@ -24,9 +25,6 @@ const Login = ({ children })=>{
|
|
|
24
25
|
const [apiError, setApiError] = React.useState();
|
|
25
26
|
const { formatMessage } = useIntl();
|
|
26
27
|
const { search: searchString } = useLocation();
|
|
27
|
-
const query = React.useMemo(()=>new URLSearchParams(searchString), [
|
|
28
|
-
searchString
|
|
29
|
-
]);
|
|
30
28
|
const navigate = useNavigate();
|
|
31
29
|
const { login } = useAuth('Login', (auth)=>auth);
|
|
32
30
|
const handleLogin = async (body)=>{
|
|
@@ -40,9 +38,7 @@ const Login = ({ children })=>{
|
|
|
40
38
|
}
|
|
41
39
|
setApiError(message);
|
|
42
40
|
} else {
|
|
43
|
-
|
|
44
|
-
const redirectUrl = redirectTo ? decodeURIComponent(redirectTo) : '/';
|
|
45
|
-
navigate(redirectUrl);
|
|
41
|
+
navigate(getRedirectTo(searchString));
|
|
46
42
|
}
|
|
47
43
|
};
|
|
48
44
|
return /*#__PURE__*/ jsx(UnauthenticatedLayout, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Login.mjs","sources":["../../../../../../../admin/src/pages/Auth/components/Login.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Main, Typography, Link } from '@strapi/design-system';\nimport camelCase from 'lodash/camelCase';\nimport { useIntl } from 'react-intl';\nimport { NavLink, useLocation, useNavigate } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { Form } from '../../../components/Form';\nimport { InputRenderer } from '../../../components/FormInputs/Renderer';\nimport { Logo } from '../../../components/UnauthenticatedLogo';\nimport { useAuth } from '../../../features/Auth';\nimport {\n UnauthenticatedLayout,\n Column,\n LayoutContent,\n} from '../../../layouts/UnauthenticatedLayout';\nimport { translatedErrors } from '../../../utils/translatedErrors';\n\nimport type { Login } from '../../../../../shared/contracts/authentication';\n\ninterface LoginProps {\n children?: React.ReactNode;\n}\n\nconst LOGIN_SCHEMA = yup.object().shape({\n email: yup\n .string()\n .nullable()\n .email({\n id: translatedErrors.email.id,\n defaultMessage: 'Not a valid email',\n })\n .required(translatedErrors.required),\n password: yup.string().required(translatedErrors.required).nullable(),\n rememberMe: yup.bool().nullable(),\n});\n\nconst Login = ({ children }: LoginProps) => {\n const [apiError, setApiError] = React.useState<string>();\n const { formatMessage } = useIntl();\n const { search: searchString } = useLocation();\n const query = React.useMemo(() => new URLSearchParams(searchString), [searchString]);\n const navigate = useNavigate();\n\n const { login } = useAuth('Login', (auth) => auth);\n\n const handleLogin = async (body: Parameters<typeof login>[0]) => {\n setApiError(undefined);\n\n const res = await login(body);\n\n if ('error' in res) {\n const message = res.error.message ?? 'Something went wrong';\n\n if (camelCase(message).toLowerCase() === 'usernotactive') {\n navigate('/auth/oops');\n return;\n }\n\n setApiError(message);\n } else {\n const redirectTo = query.get('redirectTo');\n const redirectUrl = redirectTo ? decodeURIComponent(redirectTo) : '/';\n\n navigate(redirectUrl);\n }\n };\n\n return (\n <UnauthenticatedLayout>\n <Main>\n <LayoutContent>\n <Column>\n <Logo />\n <Box paddingTop={6} paddingBottom={1}>\n <Typography variant=\"alpha\" tag=\"h1\" textAlign=\"center\">\n {formatMessage({\n id: 'Auth.form.welcome.title',\n defaultMessage: 'Welcome!',\n })}\n </Typography>\n </Box>\n <Box paddingBottom={7}>\n <Typography\n variant=\"epsilon\"\n textColor=\"neutral600\"\n textAlign=\"center\"\n display=\"block\"\n >\n {formatMessage({\n id: 'Auth.form.welcome.subtitle',\n defaultMessage: 'Log in to your Strapi account',\n })}\n </Typography>\n </Box>\n {apiError ? (\n <Typography id=\"global-form-error\" role=\"alert\" tabIndex={-1} textColor=\"danger600\">\n {apiError}\n </Typography>\n ) : null}\n </Column>\n <Form\n method=\"PUT\"\n initialValues={{\n email: '',\n password: '',\n rememberMe: false,\n }}\n onSubmit={(values) => {\n handleLogin(values);\n }}\n validationSchema={LOGIN_SCHEMA}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {[\n {\n label: formatMessage({ id: 'Auth.form.email.label', defaultMessage: 'Email' }),\n name: 'email',\n placeholder: formatMessage({\n id: 'Auth.form.email.placeholder',\n defaultMessage: 'kai@doe.com',\n }),\n required: true,\n type: 'email' as const,\n },\n {\n label: formatMessage({\n id: 'global.password',\n defaultMessage: 'Password',\n }),\n name: 'password',\n required: true,\n type: 'password' as const,\n },\n {\n label: formatMessage({\n id: 'Auth.form.rememberMe.label',\n defaultMessage: 'Remember me',\n }),\n name: 'rememberMe',\n type: 'checkbox' as const,\n },\n ].map((field) => (\n <InputRenderer key={field.name} {...field} />\n ))}\n <Button fullWidth type=\"submit\">\n {formatMessage({ id: 'Auth.form.button.login', defaultMessage: 'Login' })}\n </Button>\n </Flex>\n </Form>\n {children}\n </LayoutContent>\n <Flex justifyContent=\"center\">\n <Box paddingTop={4}>\n <Link isExternal={false} tag={NavLink} to=\"/auth/forgot-password\">\n {formatMessage({\n id: 'Auth.link.forgot-password',\n defaultMessage: 'Forgot your password?',\n })}\n </Link>\n </Box>\n </Flex>\n </Main>\n </UnauthenticatedLayout>\n );\n};\n\nexport { Login };\nexport type { LoginProps };\n"],"names":["LOGIN_SCHEMA","yup","object","shape","email","string","nullable","id","translatedErrors","defaultMessage","required","password","rememberMe","bool","Login","children","apiError","setApiError","React","useState","formatMessage","useIntl","search","searchString","useLocation","query","useMemo","URLSearchParams","navigate","useNavigate","login","useAuth","auth","handleLogin","body","undefined","res","message","error","camelCase","toLowerCase","redirectTo","get","redirectUrl","decodeURIComponent","_jsx","UnauthenticatedLayout","_jsxs","Main","LayoutContent","Column","Logo","Box","paddingTop","paddingBottom","Typography","variant","tag","textAlign","textColor","display","role","tabIndex","Form","method","initialValues","onSubmit","values","validationSchema","Flex","direction","alignItems","gap","label","name","placeholder","type","map","field","InputRenderer","Button","fullWidth","justifyContent","Link","isExternal","NavLink","to"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Login.mjs","sources":["../../../../../../../admin/src/pages/Auth/components/Login.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Main, Typography, Link } from '@strapi/design-system';\nimport camelCase from 'lodash/camelCase';\nimport { useIntl } from 'react-intl';\nimport { NavLink, useLocation, useNavigate } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { Form } from '../../../components/Form';\nimport { InputRenderer } from '../../../components/FormInputs/Renderer';\nimport { Logo } from '../../../components/UnauthenticatedLogo';\nimport { useAuth } from '../../../features/Auth';\nimport {\n UnauthenticatedLayout,\n Column,\n LayoutContent,\n} from '../../../layouts/UnauthenticatedLayout';\nimport { translatedErrors } from '../../../utils/translatedErrors';\nimport { getRedirectTo } from '../utils';\n\nimport type { Login } from '../../../../../shared/contracts/authentication';\n\ninterface LoginProps {\n children?: React.ReactNode;\n}\n\nconst LOGIN_SCHEMA = yup.object().shape({\n email: yup\n .string()\n .nullable()\n .email({\n id: translatedErrors.email.id,\n defaultMessage: 'Not a valid email',\n })\n .required(translatedErrors.required),\n password: yup.string().required(translatedErrors.required).nullable(),\n rememberMe: yup.bool().nullable(),\n});\n\nconst Login = ({ children }: LoginProps) => {\n const [apiError, setApiError] = React.useState<string>();\n const { formatMessage } = useIntl();\n const { search: searchString } = useLocation();\n const navigate = useNavigate();\n\n const { login } = useAuth('Login', (auth) => auth);\n\n const handleLogin = async (body: Parameters<typeof login>[0]) => {\n setApiError(undefined);\n\n const res = await login(body);\n\n if ('error' in res) {\n const message = res.error.message ?? 'Something went wrong';\n\n if (camelCase(message).toLowerCase() === 'usernotactive') {\n navigate('/auth/oops');\n return;\n }\n\n setApiError(message);\n } else {\n navigate(getRedirectTo(searchString));\n }\n };\n\n return (\n <UnauthenticatedLayout>\n <Main>\n <LayoutContent>\n <Column>\n <Logo />\n <Box paddingTop={6} paddingBottom={1}>\n <Typography variant=\"alpha\" tag=\"h1\" textAlign=\"center\">\n {formatMessage({\n id: 'Auth.form.welcome.title',\n defaultMessage: 'Welcome!',\n })}\n </Typography>\n </Box>\n <Box paddingBottom={7}>\n <Typography\n variant=\"epsilon\"\n textColor=\"neutral600\"\n textAlign=\"center\"\n display=\"block\"\n >\n {formatMessage({\n id: 'Auth.form.welcome.subtitle',\n defaultMessage: 'Log in to your Strapi account',\n })}\n </Typography>\n </Box>\n {apiError ? (\n <Typography id=\"global-form-error\" role=\"alert\" tabIndex={-1} textColor=\"danger600\">\n {apiError}\n </Typography>\n ) : null}\n </Column>\n <Form\n method=\"PUT\"\n initialValues={{\n email: '',\n password: '',\n rememberMe: false,\n }}\n onSubmit={(values) => {\n handleLogin(values);\n }}\n validationSchema={LOGIN_SCHEMA}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {[\n {\n label: formatMessage({ id: 'Auth.form.email.label', defaultMessage: 'Email' }),\n name: 'email',\n placeholder: formatMessage({\n id: 'Auth.form.email.placeholder',\n defaultMessage: 'kai@doe.com',\n }),\n required: true,\n type: 'email' as const,\n },\n {\n label: formatMessage({\n id: 'global.password',\n defaultMessage: 'Password',\n }),\n name: 'password',\n required: true,\n type: 'password' as const,\n },\n {\n label: formatMessage({\n id: 'Auth.form.rememberMe.label',\n defaultMessage: 'Remember me',\n }),\n name: 'rememberMe',\n type: 'checkbox' as const,\n },\n ].map((field) => (\n <InputRenderer key={field.name} {...field} />\n ))}\n <Button fullWidth type=\"submit\">\n {formatMessage({ id: 'Auth.form.button.login', defaultMessage: 'Login' })}\n </Button>\n </Flex>\n </Form>\n {children}\n </LayoutContent>\n <Flex justifyContent=\"center\">\n <Box paddingTop={4}>\n <Link isExternal={false} tag={NavLink} to=\"/auth/forgot-password\">\n {formatMessage({\n id: 'Auth.link.forgot-password',\n defaultMessage: 'Forgot your password?',\n })}\n </Link>\n </Box>\n </Flex>\n </Main>\n </UnauthenticatedLayout>\n );\n};\n\nexport { Login };\nexport type { LoginProps };\n"],"names":["LOGIN_SCHEMA","yup","object","shape","email","string","nullable","id","translatedErrors","defaultMessage","required","password","rememberMe","bool","Login","children","apiError","setApiError","React","useState","formatMessage","useIntl","search","searchString","useLocation","navigate","useNavigate","login","useAuth","auth","handleLogin","body","undefined","res","message","error","camelCase","toLowerCase","getRedirectTo","_jsx","UnauthenticatedLayout","_jsxs","Main","LayoutContent","Column","Logo","Box","paddingTop","paddingBottom","Typography","variant","tag","textAlign","textColor","display","role","tabIndex","Form","method","initialValues","onSubmit","values","validationSchema","Flex","direction","alignItems","gap","label","name","placeholder","type","map","field","InputRenderer","Button","fullWidth","justifyContent","Link","isExternal","NavLink","to"],"mappings":"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"}
|