From 08b4ce2ca468dbf52e8b2c70f3451e9ffb0596c9 Mon Sep 17 00:00:00 2001 From: Daniel Cousens <413395+dcousens@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:35:34 +1000 Subject: [PATCH] remove authenticatedItem from @keystone-6/core/admin-ui --- .changeset/admin-ui-navigation.md | 5 ++ .changeset/remove-end-session.md | 5 ++ .../admin/components/CustomNavigation.tsx | 8 +-- examples/custom-session-jwt/schema.graphql | 1 - .../custom-session-next-auth/schema.graphql | 1 - .../custom-session-passport/schema.graphql | 1 - examples/custom-session/schema.graphql | 1 - .../usecase-blog-moderated/schema.graphql | 1 - .../auth/components/Navigation/package.json | 4 ++ packages/auth/package.json | 5 ++ packages/auth/src/components/Navigation.tsx | 43 +++++++++++++ .../auth/src/components/SigninContainer.tsx | 9 ++- .../src}/components/SignoutButton.tsx | 7 +- packages/auth/src/gql/getBaseAuthSchema.ts | 7 ++ packages/auth/src/index.ts | 10 ++- packages/auth/src/pages/InitPage.tsx | 8 +-- packages/auth/src/pages/SigninPage.tsx | 8 ++- packages/auth/src/templates/config.ts | 11 ++++ packages/auth/src/templates/init.ts | 21 +++--- packages/auth/src/templates/signin.ts | 14 ++-- .../src/admin-ui/components/Navigation.tsx | 64 +++++++------------ packages/core/src/admin-ui/context.tsx | 2 - .../core/src/lib/core/initialise-lists.ts | 3 +- packages/core/src/lib/createGraphQLSchema.ts | 12 +--- packages/core/src/types/admin-meta.ts | 7 -- 25 files changed, 157 insertions(+), 101 deletions(-) create mode 100644 .changeset/admin-ui-navigation.md create mode 100644 .changeset/remove-end-session.md create mode 100644 packages/auth/components/Navigation/package.json create mode 100644 packages/auth/src/components/Navigation.tsx rename packages/{core/src/admin-ui => auth/src}/components/SignoutButton.tsx (82%) create mode 100644 packages/auth/src/templates/config.ts diff --git a/.changeset/admin-ui-navigation.md b/.changeset/admin-ui-navigation.md new file mode 100644 index 00000000000..892ba0d6ce1 --- /dev/null +++ b/.changeset/admin-ui-navigation.md @@ -0,0 +1,5 @@ +--- +"@keystone-6/core": major +--- + +Removes `authenticatedItem` from `@keystone-6/core/admin-ui/components` exports diff --git a/.changeset/remove-end-session.md b/.changeset/remove-end-session.md new file mode 100644 index 00000000000..35482f2e091 --- /dev/null +++ b/.changeset/remove-end-session.md @@ -0,0 +1,5 @@ +--- +"@keystone-6/core": major +--- + +Removes the `EndSession` GraphQL mutation addition when `context.session.end` is defined, extend this yourself if required diff --git a/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx b/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx index 075557fee52..429ded8ebad 100644 --- a/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx +++ b/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx @@ -4,12 +4,12 @@ import { ListNavItems, NavigationContainer, NavItem } from '@keystone-6/core/adm import type { NavigationProps } from '@keystone-6/core/admin-ui/components' -export function CustomNavigation ({ lists, authenticatedItem }: NavigationProps) { +export function CustomNavigation ({ lists }: NavigationProps) { return ( - - Dashboard + + Dashboard - Keystone Docs + Keystone Docs ) } diff --git a/examples/custom-session-jwt/schema.graphql b/examples/custom-session-jwt/schema.graphql index 8cf7376b705..887ea40c43a 100644 --- a/examples/custom-session-jwt/schema.graphql +++ b/examples/custom-session-jwt/schema.graphql @@ -148,7 +148,6 @@ type Mutation { updateUsers(data: [UserUpdateArgs!]!): [User] deleteUser(where: UserWhereUniqueInput!): User deleteUsers(where: [UserWhereUniqueInput!]!): [User] - endSession: Boolean! } type Query { diff --git a/examples/custom-session-next-auth/schema.graphql b/examples/custom-session-next-auth/schema.graphql index 70ed344b290..97e21e950b6 100644 --- a/examples/custom-session-next-auth/schema.graphql +++ b/examples/custom-session-next-auth/schema.graphql @@ -182,7 +182,6 @@ type Mutation { updateAuthors(data: [AuthorUpdateArgs!]!): [Author] deleteAuthor(where: AuthorWhereUniqueInput!): Author deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] - endSession: Boolean! } type Query { diff --git a/examples/custom-session-passport/schema.graphql b/examples/custom-session-passport/schema.graphql index 70ed344b290..97e21e950b6 100644 --- a/examples/custom-session-passport/schema.graphql +++ b/examples/custom-session-passport/schema.graphql @@ -182,7 +182,6 @@ type Mutation { updateAuthors(data: [AuthorUpdateArgs!]!): [Author] deleteAuthor(where: AuthorWhereUniqueInput!): Author deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] - endSession: Boolean! } type Query { diff --git a/examples/custom-session/schema.graphql b/examples/custom-session/schema.graphql index 8cf7376b705..887ea40c43a 100644 --- a/examples/custom-session/schema.graphql +++ b/examples/custom-session/schema.graphql @@ -148,7 +148,6 @@ type Mutation { updateUsers(data: [UserUpdateArgs!]!): [User] deleteUser(where: UserWhereUniqueInput!): User deleteUsers(where: [UserWhereUniqueInput!]!): [User] - endSession: Boolean! } type Query { diff --git a/examples/usecase-blog-moderated/schema.graphql b/examples/usecase-blog-moderated/schema.graphql index 7345f897cd7..e813a19da9a 100644 --- a/examples/usecase-blog-moderated/schema.graphql +++ b/examples/usecase-blog-moderated/schema.graphql @@ -324,7 +324,6 @@ type Mutation { updateUsers(data: [UserUpdateArgs!]!): [User] deleteUser(where: UserWhereUniqueInput!): User deleteUsers(where: [UserWhereUniqueInput!]!): [User] - endSession: Boolean! } type Query { diff --git a/packages/auth/components/Navigation/package.json b/packages/auth/components/Navigation/package.json new file mode 100644 index 00000000000..7d28b00c53f --- /dev/null +++ b/packages/auth/components/Navigation/package.json @@ -0,0 +1,4 @@ +{ + "main": "dist/keystone-6-auth-components-Navigation.cjs.js", + "module": "dist/keystone-6-auth-components-Navigation.esm.js" +} diff --git a/packages/auth/package.json b/packages/auth/package.json index 8c271b817c7..fb8b3d88ff2 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -17,6 +17,10 @@ "module": "./pages/SigninPage/dist/keystone-6-auth-pages-SigninPage.esm.js", "default": "./pages/SigninPage/dist/keystone-6-auth-pages-SigninPage.cjs.js" }, + "./components/Navigation": { + "module": "./components/Navigation/dist/keystone-6-auth-components-Navigation.esm.js", + "default": "./components/Navigation/dist/keystone-6-auth-components-Navigation.cjs.js" + }, "./package.json": "./package.json" }, "dependencies": { @@ -41,6 +45,7 @@ "preconstruct": { "entrypoints": [ "index.ts", + "components/Navigation.tsx", "pages/*.tsx" ] }, diff --git a/packages/auth/src/components/Navigation.tsx b/packages/auth/src/components/Navigation.tsx new file mode 100644 index 00000000000..10904ca4f2a --- /dev/null +++ b/packages/auth/src/components/Navigation.tsx @@ -0,0 +1,43 @@ +import React from 'react' + +import { + ListNavItems, + NavigationContainer, + NavItem +} from '@keystone-6/core/admin-ui/components' +import type { NavigationProps } from '@keystone-6/core/admin-ui/components' +import SignoutButton from './SignoutButton' + +function Footer ({ authItem }: { authItem: AuthenticatedItem | undefined }) { + return ( + + + + + ) +} + +function AuthItem ({ item }: { item: AuthenticatedItem | undefined }) { + if (!item || item.state !== 'authenticated') { + return null + } + + return ( + + + + Signed in as {item.label} + + + ) +} + +export default function Navigation ({ lists }: NavigationProps) { + return ( + + Dashboard + + + + ) +} diff --git a/packages/auth/src/components/SigninContainer.tsx b/packages/auth/src/components/SigninContainer.tsx index 759004aaf97..0dbb11d7e95 100644 --- a/packages/auth/src/components/SigninContainer.tsx +++ b/packages/auth/src/components/SigninContainer.tsx @@ -3,7 +3,12 @@ import { type ReactNode } from 'react' -import { jsx, Box, Center, useTheme } from '@keystone-ui/core' +import { + jsx, + Box, + Center, + useTheme +} from '@keystone-ui/core' import { Head } from '@keystone-6/core/admin-ui/router' type SigninContainerProps = { @@ -11,7 +16,7 @@ type SigninContainerProps = { title?: string } -export const SigninContainer = ({ children, title }: SigninContainerProps) => { +export function SigninContainer ({ children, title }: SigninContainerProps) { const { colors, shadow } = useTheme() return (
diff --git a/packages/core/src/admin-ui/components/SignoutButton.tsx b/packages/auth/src/components/SignoutButton.tsx similarity index 82% rename from packages/core/src/admin-ui/components/SignoutButton.tsx rename to packages/auth/src/components/SignoutButton.tsx index 5955ccf9bc8..685a50029dd 100644 --- a/packages/core/src/admin-ui/components/SignoutButton.tsx +++ b/packages/auth/src/components/SignoutButton.tsx @@ -1,7 +1,10 @@ -import { ActionButton, type ActionButtonProps } from '@keystar/ui/button' +import { + type ActionButtonProps + ActionButton, +} from '@keystar/ui/button' import { useEffect } from 'react' -import { useMutation, gql } from '../apollo' +import { useMutation, gql } from '@keystone-6/core/admin-ui/apollo' const END_SESSION = gql` mutation EndSession { diff --git a/packages/auth/src/gql/getBaseAuthSchema.ts b/packages/auth/src/gql/getBaseAuthSchema.ts index c9c856f5b88..7540f3227dc 100644 --- a/packages/auth/src/gql/getBaseAuthSchema.ts +++ b/packages/auth/src/gql/getBaseAuthSchema.ts @@ -77,6 +77,13 @@ export function getBaseAuthSchema ({ }), }, mutation: { + endSession: graphql.field({ + type: graphql.nonNull(graphql.Boolean), + async resolve (rootVal, args, context) { + await context.sessionStrategy?.end({ context }) + return true + }, + }), [gqlNames.authenticateItemWithPassword]: graphql.field({ type: AuthenticationResult, args: { diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 68448486a4c..cd6232e5aef 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -10,8 +10,9 @@ import { password, timestamp } from '@keystone-6/core/fields' import type { AuthConfig, AuthGqlNames } from './types' import { getSchemaExtension } from './schema' -import { signinTemplate } from './templates/signin' -import { initTemplate } from './templates/init' +import configTemplate from './templates/config' +import signinTemplate from './templates/signin' +import initTemplate from './templates/init' export type AuthSession = { listKey: string // TODO: use ListTypeInfo @@ -106,6 +107,11 @@ export function createAuth ({ src: signinTemplate({ gqlNames, identityField, secretField }), outputPath: 'pages/signin.js', }, + { + mode: 'write', + src: configTemplate(), + outputPath: 'config.ts', + }, ] if (initFirstItem) { filesToWrite.push({ diff --git a/packages/auth/src/pages/InitPage.tsx b/packages/auth/src/pages/InitPage.tsx index cc92c2ee987..fb9339416ff 100644 --- a/packages/auth/src/pages/InitPage.tsx +++ b/packages/auth/src/pages/InitPage.tsx @@ -8,15 +8,15 @@ import { jsx, H1, Stack, Inline, VisuallyHidden } from '@keystone-ui/core' import { Button } from '@keystone-ui/button' import { Checkbox, TextInput } from '@keystone-ui/fields' import { type FieldMeta } from '@keystone-6/core/types' -import isDeepEqual from 'fast-deep-equal' import { gql, useMutation } from '@keystone-6/core/admin-ui/apollo' -import { useReinitContext, useKeystone } from '@keystone-6/core/admin-ui/context' +import { useKeystone } from '@keystone-6/core/admin-ui/context' import { useRouter, Link } from '@keystone-6/core/admin-ui/router' import { GraphQLErrorNotice } from '@keystone-6/core/admin-ui/components' import { Fields, - serializeValueToObjByFieldKey, + itemValueToGraphQL, + getDefaultItemValue, useInvalidFields, } from '@keystone-6/core/admin-ui/utils' import { guessEmailFromValue, validEmail } from '../lib/emailHeuristics' @@ -88,7 +88,7 @@ function Welcome ({ value, onContinue }: { value: any, onContinue: () => void }) >

Welcome

- ['initFirstItem']> -} - -export const initTemplate = ({ listKey, initFirstItem }: InitTemplateArgs) => { +}) { // -- TEMPLATE START - return `import { getInitPage } from '@keystone-6/auth/pages/InitPage'; - -const fieldPaths = ${JSON.stringify(initFirstItem.fields)}; + return `import { getInitPage } from '@keystone-6/auth/pages/InitPage' export default getInitPage(${JSON.stringify({ - listKey, - fieldPaths: initFirstItem.fields, - enableWelcome: !initFirstItem.skipKeystoneWelcome, - })}); + listKey, + fieldPaths: initFirstItem.fields, + enableWelcome: !initFirstItem.skipKeystoneWelcome, +})}) ` // -- TEMPLATE END } diff --git a/packages/auth/src/templates/signin.ts b/packages/auth/src/templates/signin.ts index 6e333babc59..acf7969bd15 100644 --- a/packages/auth/src/templates/signin.ts +++ b/packages/auth/src/templates/signin.ts @@ -1,6 +1,6 @@ import { type AuthGqlNames } from '../types' -export const signinTemplate = ({ +export default ({ gqlNames, identityField, secretField, @@ -13,12 +13,12 @@ export const signinTemplate = ({ return `import { getSigninPage } from '@keystone-6/auth/pages/SigninPage' export default getSigninPage(${JSON.stringify({ - identityField: identityField, - secretField: secretField, - mutationName: gqlNames.authenticateItemWithPassword, - successTypename: gqlNames.ItemAuthenticationWithPasswordSuccess, - failureTypename: gqlNames.ItemAuthenticationWithPasswordFailure, - })}); + identityField: identityField, + secretField: secretField, + mutationName: gqlNames.authenticateItemWithPassword, + successTypename: gqlNames.ItemAuthenticationWithPasswordSuccess, + failureTypename: gqlNames.ItemAuthenticationWithPasswordFailure, +})}) ` // -- TEMPLATE END } diff --git a/packages/core/src/admin-ui/components/Navigation.tsx b/packages/core/src/admin-ui/components/Navigation.tsx index fbe55cbe8de..cdfc7255027 100644 --- a/packages/core/src/admin-ui/components/Navigation.tsx +++ b/packages/core/src/admin-ui/components/Navigation.tsx @@ -14,9 +14,9 @@ import { Notice } from '@keystar/ui/notice' import { TooltipTrigger, Tooltip } from '@keystar/ui/tooltip' import { Text } from '@keystar/ui/typography' -import { type NavigationProps, type ListMeta, type AuthenticatedItem } from '../../types' +import { type NavigationProps, type ListMeta } from '../../types' import { useKeystone } from '../context' -import { SignoutButton } from './SignoutButton' +import { Link } from '../router' type NavItemProps = { /** @@ -35,7 +35,7 @@ type NavItemProps = { isSelected?: boolean } -type NavigationContainerProps = Partial> & { +type NavigationContainerProps = { children: ReactNode } @@ -64,12 +64,11 @@ export const NavDivider = Divider * A navigation item represents a page in the admin UI. Prefer `ListNavItems` * for managing navigation between lists. */ -export const NavItem = (props: NavItemProps) => { +export function NavItem (props: NavItemProps) { const { children, href, isSelected: isSelectedProp } = props const router = useRouter() let ariaCurrent: 'page' | boolean | undefined = isSelectedProp - if (!ariaCurrent) { if (router.pathname === href) { ariaCurrent = 'page' @@ -93,13 +92,13 @@ export const NavItem = (props: NavItemProps) => { * markup around navigation items, as well as the different states of * the `authenticatedItem` element. */ -export const NavigationContainer = ({ authenticatedItem, children }: NavigationContainerProps) => { +export function NavigationContainer ({ children }: NavigationContainerProps) { return ( - - + + {children} -