Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add next-auth using a custom session strategy #8582

Merged
merged 21 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import NextAuth from 'next-auth';
import { nextAuthOptions } from '../../../../session';

export default NextAuth(nextAuthOptions);
48 changes: 48 additions & 0 deletions examples/custom-session-next-auth/keystone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { config } from '@keystone-6/core';
import { fixPrismaPath } from '../example-utils';
import { lists } from './schema';

import { Session, nextAuthSessionStrategy } from './session';
import type { TypeInfo } from '.keystone/types';

// WARNING: this example is for demonstration purposes only
// as with each of our examples, it has not been vetted
// or tested for any particular usage

export default config<TypeInfo<Session>>({
db: {
provider: 'sqlite',
url: process.env.DATABASE_URL || 'file:./keystone-example.db',

// WARNING: this is only needed for our monorepo examples, dont do this
...fixPrismaPath,
},
ui: {
// the following api routes are required for nextauth.js
publicPages: [
'/api/auth/csrf',
'/api/auth/signin',
'/api/auth/callback',
'/api/auth/session',
'/api/auth/providers',
'/api/auth/signout',
'/api/auth/error',

// each provider will need a separate callback and signin page listed here
'/api/auth/signin/github',
'/api/auth/callback/github',
],

// adding page middleware ensures that users are redirected to the signin page if they are not signed in.
pageMiddleware: async ({ wasAccessAllowed }) => {
if (wasAccessAllowed) return;
return {
kind: 'redirect',
to: '/api/auth/signin',
};
},
},
lists,
// you can find out more at https://keystonejs.com/docs/apis/session#session-api
session: nextAuthSessionStrategy,
});
21 changes: 21 additions & 0 deletions examples/custom-session-next-auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@keystone-6/custom-session-next-auth",
"version": "0.1.1",
"private": true,
"license": "MIT",
"scripts": {
"dev": "keystone dev",
"start": "keystone start",
"build": "keystone build",
"postinstall": "keystone postinstall"
},
"dependencies": {
"@keystone-6/core": "^5.0.0",
"@prisma/client": "^4.14.0",
"next-auth": "^4.22.1"
},
"devDependencies": {
"prisma": "^4.14.0",
"typescript": "~5.0.0"
}
}
7 changes: 7 additions & 0 deletions examples/custom-session-next-auth/sandbox.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"template": "node",
"container": {
"startScript": "keystone dev",
"node": "16"
}
}
303 changes: 303 additions & 0 deletions examples/custom-session-next-auth/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
# This file is automatically generated by Keystone, do not modify it manually.
# Modify your Keystone config when you want to change this.

type Post {
id: ID!
title: String
content: String
author: Author
}

input PostWhereUniqueInput {
id: ID
}

input PostWhereInput {
AND: [PostWhereInput!]
OR: [PostWhereInput!]
NOT: [PostWhereInput!]
id: IDFilter
title: StringFilter
content: StringFilter
author: AuthorWhereInput
}

input IDFilter {
equals: ID
in: [ID!]
notIn: [ID!]
lt: ID
lte: ID
gt: ID
gte: ID
not: IDFilter
}

input StringFilter {
equals: String
in: [String!]
notIn: [String!]
lt: String
lte: String
gt: String
gte: String
contains: String
startsWith: String
endsWith: String
not: NestedStringFilter
}

input NestedStringFilter {
equals: String
in: [String!]
notIn: [String!]
lt: String
lte: String
gt: String
gte: String
contains: String
startsWith: String
endsWith: String
not: NestedStringFilter
}

input PostOrderByInput {
id: OrderDirection
title: OrderDirection
content: OrderDirection
}

enum OrderDirection {
asc
desc
}

input PostUpdateInput {
title: String
content: String
author: AuthorRelateToOneForUpdateInput
}

input AuthorRelateToOneForUpdateInput {
create: AuthorCreateInput
connect: AuthorWhereUniqueInput
disconnect: Boolean
}

input PostUpdateArgs {
where: PostWhereUniqueInput!
data: PostUpdateInput!
}

input PostCreateInput {
title: String
content: String
author: AuthorRelateToOneForCreateInput
}

input AuthorRelateToOneForCreateInput {
create: AuthorCreateInput
connect: AuthorWhereUniqueInput
}

type Author {
id: ID!
authId: String
name: String
posts(where: PostWhereInput! = {}, orderBy: [PostOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: PostWhereUniqueInput): [Post!]
postsCount(where: PostWhereInput! = {}): Int
}

input AuthorWhereUniqueInput {
id: ID
authId: String
}

input AuthorWhereInput {
AND: [AuthorWhereInput!]
OR: [AuthorWhereInput!]
NOT: [AuthorWhereInput!]
id: IDFilter
authId: StringFilter
name: StringFilter
posts: PostManyRelationFilter
}

input PostManyRelationFilter {
every: PostWhereInput
some: PostWhereInput
none: PostWhereInput
}

input AuthorOrderByInput {
id: OrderDirection
authId: OrderDirection
name: OrderDirection
}

input AuthorUpdateInput {
authId: String
name: String
posts: PostRelateToManyForUpdateInput
}

input PostRelateToManyForUpdateInput {
disconnect: [PostWhereUniqueInput!]
set: [PostWhereUniqueInput!]
create: [PostCreateInput!]
connect: [PostWhereUniqueInput!]
}

input AuthorUpdateArgs {
where: AuthorWhereUniqueInput!
data: AuthorUpdateInput!
}

input AuthorCreateInput {
authId: String
name: String
posts: PostRelateToManyForCreateInput
}

input PostRelateToManyForCreateInput {
create: [PostCreateInput!]
connect: [PostWhereUniqueInput!]
}

"""
The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf")

type Mutation {
createPost(data: PostCreateInput!): Post
createPosts(data: [PostCreateInput!]!): [Post]
updatePost(where: PostWhereUniqueInput!, data: PostUpdateInput!): Post
updatePosts(data: [PostUpdateArgs!]!): [Post]
deletePost(where: PostWhereUniqueInput!): Post
deletePosts(where: [PostWhereUniqueInput!]!): [Post]
createAuthor(data: AuthorCreateInput!): Author
createAuthors(data: [AuthorCreateInput!]!): [Author]
updateAuthor(where: AuthorWhereUniqueInput!, data: AuthorUpdateInput!): Author
updateAuthors(data: [AuthorUpdateArgs!]!): [Author]
deleteAuthor(where: AuthorWhereUniqueInput!): Author
deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author]
endSession: Boolean!
}

type Query {
posts(where: PostWhereInput! = {}, orderBy: [PostOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: PostWhereUniqueInput): [Post!]
post(where: PostWhereUniqueInput!): Post
postsCount(where: PostWhereInput! = {}): Int
authors(where: AuthorWhereInput! = {}, orderBy: [AuthorOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: AuthorWhereUniqueInput): [Author!]
author(where: AuthorWhereUniqueInput!): Author
authorsCount(where: AuthorWhereInput! = {}): Int
keystone: KeystoneMeta!
}

type KeystoneMeta {
adminMeta: KeystoneAdminMeta!
}

type KeystoneAdminMeta {
lists: [KeystoneAdminUIListMeta!]!
list(key: String!): KeystoneAdminUIListMeta
}

type KeystoneAdminUIListMeta {
key: String!
itemQueryName: String!
listQueryName: String!
hideCreate: Boolean!
hideDelete: Boolean!
path: String!
label: String!
singular: String!
plural: String!
description: String
initialColumns: [String!]!
pageSize: Int!
labelField: String!
fields: [KeystoneAdminUIFieldMeta!]!
groups: [KeystoneAdminUIFieldGroupMeta!]!
initialSort: KeystoneAdminUISort
isHidden: Boolean!
isSingleton: Boolean!
}

type KeystoneAdminUIFieldMeta {
path: String!
label: String!
description: String
isOrderable: Boolean!
isFilterable: Boolean!
isNonNull: [KeystoneAdminUIFieldMetaIsNonNull!]
fieldMeta: JSON
viewsIndex: Int!
customViewsIndex: Int
createView: KeystoneAdminUIFieldMetaCreateView!
listView: KeystoneAdminUIFieldMetaListView!
itemView(id: ID): KeystoneAdminUIFieldMetaItemView
search: QueryMode
}

enum KeystoneAdminUIFieldMetaIsNonNull {
read
create
update
}

type KeystoneAdminUIFieldMetaCreateView {
fieldMode: KeystoneAdminUIFieldMetaCreateViewFieldMode!
}

enum KeystoneAdminUIFieldMetaCreateViewFieldMode {
edit
hidden
}

type KeystoneAdminUIFieldMetaListView {
fieldMode: KeystoneAdminUIFieldMetaListViewFieldMode!
}

enum KeystoneAdminUIFieldMetaListViewFieldMode {
read
hidden
}

type KeystoneAdminUIFieldMetaItemView {
fieldMode: KeystoneAdminUIFieldMetaItemViewFieldMode
fieldPosition: KeystoneAdminUIFieldMetaItemViewFieldPosition
}

enum KeystoneAdminUIFieldMetaItemViewFieldMode {
edit
read
hidden
}

enum KeystoneAdminUIFieldMetaItemViewFieldPosition {
form
sidebar
}

enum QueryMode {
default
insensitive
}

type KeystoneAdminUIFieldGroupMeta {
label: String!
description: String
fields: [KeystoneAdminUIFieldMeta!]!
}

type KeystoneAdminUISort {
field: String!
direction: KeystoneAdminUISortDirection!
}

enum KeystoneAdminUISortDirection {
ASC
DESC
}
Loading