add: GitHub authentication
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/admin-bar": "latest",
|
"@payloadcms/admin-bar": "latest",
|
||||||
|
"@payloadcms/db-sqlite": "latest",
|
||||||
"@payloadcms/live-preview-react": "latest",
|
"@payloadcms/live-preview-react": "latest",
|
||||||
"@payloadcms/next": "latest",
|
"@payloadcms/next": "latest",
|
||||||
"@payloadcms/payload-cloud": "latest",
|
"@payloadcms/payload-cloud": "latest",
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@radix-ui/react-slot": "^1.0.2",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
|
"auth": "^1.2.3",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
@@ -41,16 +43,17 @@
|
|||||||
"graphql": "^16.8.2",
|
"graphql": "^16.8.2",
|
||||||
"lucide-react": "^0.378.0",
|
"lucide-react": "^0.378.0",
|
||||||
"next": "15.2.3",
|
"next": "15.2.3",
|
||||||
|
"next-auth": "5.0.0-beta.25",
|
||||||
"next-sitemap": "^4.2.3",
|
"next-sitemap": "^4.2.3",
|
||||||
"payload": "latest",
|
"payload": "latest",
|
||||||
|
"payload-authjs": "^0.7.1",
|
||||||
"prism-react-renderer": "^2.3.1",
|
"prism-react-renderer": "^2.3.1",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-hook-form": "7.45.4",
|
"react-hook-form": "7.45.4",
|
||||||
"sharp": "0.32.6",
|
"sharp": "0.32.6",
|
||||||
"tailwind-merge": "^2.3.0",
|
"tailwind-merge": "^2.3.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7"
|
||||||
"@payloadcms/db-sqlite": "latest"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
|||||||
10222
pnpm-lock.yaml
generated
10222
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
9
src/_middleware.ts
Normal file
9
src/_middleware.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import NextAuth from "next-auth";
|
||||||
|
import { authConfig } from "./auth.config";
|
||||||
|
|
||||||
|
const { auth: middleware } = NextAuth(authConfig);
|
||||||
|
export default middleware;
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
|
||||||
|
};
|
||||||
14
src/app/(frontend)/login/page.tsx
Normal file
14
src/app/(frontend)/login/page.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { signIn } from "@/auth";
|
||||||
|
|
||||||
|
export default function SignInButton() {
|
||||||
|
return (
|
||||||
|
<form
|
||||||
|
action={async () => {
|
||||||
|
"use server";
|
||||||
|
await signIn("github");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<button type="submit">Sign In</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import { LinkToDoc as LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634 } from '@payloa
|
|||||||
import { ReindexButton as ReindexButton_aead06e4cbf6b2620c5c51c9ab283634 } from '@payloadcms/plugin-search/client'
|
import { ReindexButton as ReindexButton_aead06e4cbf6b2620c5c51c9ab283634 } from '@payloadcms/plugin-search/client'
|
||||||
import { RowLabel as RowLabel_ec255a65fa6fa8d1faeb09cf35284224 } from '@/Header/RowLabel'
|
import { RowLabel as RowLabel_ec255a65fa6fa8d1faeb09cf35284224 } from '@/Header/RowLabel'
|
||||||
import { RowLabel as RowLabel_1f6ff6ff633e3695d348f4f3c58f1466 } from '@/Footer/RowLabel'
|
import { RowLabel as RowLabel_1f6ff6ff633e3695d348f4f3c58f1466 } from '@/Footer/RowLabel'
|
||||||
|
import { SignInWithAuthjsButton as SignInWithAuthjsButton_06d0cb594d8f6ba2ac35015f930c882e } from 'payload-authjs/components'
|
||||||
import { default as default_1a7510af427896d367a49dbf838d2de6 } from '@/components/BeforeDashboard'
|
import { default as default_1a7510af427896d367a49dbf838d2de6 } from '@/components/BeforeDashboard'
|
||||||
import { default as default_8a7ab0eb7ab5c511aba12e68480bfe5e } from '@/components/BeforeLogin'
|
import { default as default_8a7ab0eb7ab5c511aba12e68480bfe5e } from '@/components/BeforeLogin'
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ export const importMap = {
|
|||||||
"@payloadcms/plugin-search/client#ReindexButton": ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
|
"@payloadcms/plugin-search/client#ReindexButton": ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
|
||||||
"@/Header/RowLabel#RowLabel": RowLabel_ec255a65fa6fa8d1faeb09cf35284224,
|
"@/Header/RowLabel#RowLabel": RowLabel_ec255a65fa6fa8d1faeb09cf35284224,
|
||||||
"@/Footer/RowLabel#RowLabel": RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
|
"@/Footer/RowLabel#RowLabel": RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
|
||||||
|
"payload-authjs/components#SignInWithAuthjsButton": SignInWithAuthjsButton_06d0cb594d8f6ba2ac35015f930c882e,
|
||||||
"@/components/BeforeDashboard#default": default_1a7510af427896d367a49dbf838d2de6,
|
"@/components/BeforeDashboard#default": default_1a7510af427896d367a49dbf838d2de6,
|
||||||
"@/components/BeforeLogin#default": default_8a7ab0eb7ab5c511aba12e68480bfe5e
|
"@/components/BeforeLogin#default": default_8a7ab0eb7ab5c511aba12e68480bfe5e
|
||||||
}
|
}
|
||||||
|
|||||||
2
src/app/(payload)/api/auth/[...nextauth]/route.ts
Normal file
2
src/app/(payload)/api/auth/[...nextauth]/route.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import { handlers } from "@/auth" // Referring to the auth.ts we just created
|
||||||
|
export const { GET, POST } = handlers
|
||||||
9
src/auth.config.ts
Normal file
9
src/auth.config.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { NextAuthConfig } from "next-auth";
|
||||||
|
import github from "next-auth/providers/github";
|
||||||
|
|
||||||
|
export const authConfig: NextAuthConfig = {
|
||||||
|
providers: [github],
|
||||||
|
callbacks: {
|
||||||
|
authorized: ({ auth }) => !!auth,
|
||||||
|
},
|
||||||
|
};
|
||||||
10
src/auth.ts
Normal file
10
src/auth.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import payloadConfig from "@payload-config";
|
||||||
|
import NextAuth from "next-auth";
|
||||||
|
import { withPayload } from "payload-authjs";
|
||||||
|
import { authConfig } from "./auth.config";
|
||||||
|
|
||||||
|
export const { handlers, signIn, signOut, auth } = NextAuth(
|
||||||
|
withPayload(authConfig, {
|
||||||
|
payloadConfig,
|
||||||
|
}),
|
||||||
|
);
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import type { CollectionConfig } from 'payload'
|
|
||||||
|
|
||||||
import { authenticated } from '../../access/authenticated'
|
|
||||||
|
|
||||||
export const Users: CollectionConfig = {
|
|
||||||
slug: 'users',
|
|
||||||
access: {
|
|
||||||
admin: authenticated,
|
|
||||||
create: authenticated,
|
|
||||||
delete: authenticated,
|
|
||||||
read: authenticated,
|
|
||||||
update: authenticated,
|
|
||||||
},
|
|
||||||
admin: {
|
|
||||||
defaultColumns: ['name', 'email'],
|
|
||||||
useAsTitle: 'name',
|
|
||||||
},
|
|
||||||
auth: true,
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'name',
|
|
||||||
type: 'text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
timestamps: true,
|
|
||||||
}
|
|
||||||
7
src/collections/users.ts
Normal file
7
src/collections/users.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// users.ts
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
const Users: CollectionConfig = {
|
||||||
|
slug: "users",
|
||||||
|
fields: [],
|
||||||
|
};
|
||||||
@@ -167,7 +167,7 @@ export interface Paper {
|
|||||||
};
|
};
|
||||||
authors: {
|
authors: {
|
||||||
profilePicture: number | Media;
|
profilePicture: number | Media;
|
||||||
user: number | User;
|
user: string | User;
|
||||||
position: 'leader' | 'member';
|
position: 'leader' | 'member';
|
||||||
description: string;
|
description: string;
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
@@ -286,18 +286,21 @@ export interface Media {
|
|||||||
* via the `definition` "users".
|
* via the `definition` "users".
|
||||||
*/
|
*/
|
||||||
export interface User {
|
export interface User {
|
||||||
id: number;
|
id: string;
|
||||||
|
email: string;
|
||||||
|
emailVerified?: string | null;
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
|
image?: string | null;
|
||||||
|
accounts?:
|
||||||
|
| {
|
||||||
|
id?: string | null;
|
||||||
|
provider: string;
|
||||||
|
providerAccountId: string;
|
||||||
|
type: string;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
email: string;
|
|
||||||
resetPasswordToken?: string | null;
|
|
||||||
resetPasswordExpiration?: string | null;
|
|
||||||
salt?: string | null;
|
|
||||||
hash?: string | null;
|
|
||||||
loginAttempts?: number | null;
|
|
||||||
lockUntil?: string | null;
|
|
||||||
password?: string | null;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
@@ -399,7 +402,7 @@ export interface Post {
|
|||||||
description?: string | null;
|
description?: string | null;
|
||||||
};
|
};
|
||||||
publishedAt?: string | null;
|
publishedAt?: string | null;
|
||||||
authors?: (number | User)[] | null;
|
authors?: (string | User)[] | null;
|
||||||
populatedAuthors?:
|
populatedAuthors?:
|
||||||
| {
|
| {
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
@@ -973,7 +976,7 @@ export interface PayloadLockedDocument {
|
|||||||
} | null)
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'users';
|
relationTo: 'users';
|
||||||
value: number | User;
|
value: string | User;
|
||||||
} | null)
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'redirects';
|
relationTo: 'redirects';
|
||||||
@@ -998,7 +1001,7 @@ export interface PayloadLockedDocument {
|
|||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user: {
|
||||||
relationTo: 'users';
|
relationTo: 'users';
|
||||||
value: number | User;
|
value: string | User;
|
||||||
};
|
};
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -1011,7 +1014,7 @@ export interface PayloadPreference {
|
|||||||
id: number;
|
id: number;
|
||||||
user: {
|
user: {
|
||||||
relationTo: 'users';
|
relationTo: 'users';
|
||||||
value: number | User;
|
value: string | User;
|
||||||
};
|
};
|
||||||
key?: string | null;
|
key?: string | null;
|
||||||
value?:
|
value?:
|
||||||
@@ -1367,16 +1370,21 @@ export interface CategoriesSelect<T extends boolean = true> {
|
|||||||
* via the `definition` "users_select".
|
* via the `definition` "users_select".
|
||||||
*/
|
*/
|
||||||
export interface UsersSelect<T extends boolean = true> {
|
export interface UsersSelect<T extends boolean = true> {
|
||||||
|
id?: T;
|
||||||
|
email?: T;
|
||||||
|
emailVerified?: T;
|
||||||
name?: T;
|
name?: T;
|
||||||
|
image?: T;
|
||||||
|
accounts?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
id?: T;
|
||||||
|
provider?: T;
|
||||||
|
providerAccountId?: T;
|
||||||
|
type?: T;
|
||||||
|
};
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
email?: T;
|
|
||||||
resetPasswordToken?: T;
|
|
||||||
resetPasswordExpiration?: T;
|
|
||||||
salt?: T;
|
|
||||||
hash?: T;
|
|
||||||
loginAttempts?: T;
|
|
||||||
lockUntil?: T;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
@@ -1754,7 +1762,7 @@ export interface TaskSchedulePublish {
|
|||||||
value: number | Post;
|
value: number | Post;
|
||||||
} | null);
|
} | null);
|
||||||
global?: string | null;
|
global?: string | null;
|
||||||
user?: (number | null) | User;
|
user?: (string | null) | User;
|
||||||
};
|
};
|
||||||
output?: unknown;
|
output?: unknown;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { Categories } from './collections/Categories'
|
|||||||
import { Media } from './collections/Media'
|
import { Media } from './collections/Media'
|
||||||
import { Pages } from './collections/Pages'
|
import { Pages } from './collections/Pages'
|
||||||
import { Posts } from './collections/Posts'
|
import { Posts } from './collections/Posts'
|
||||||
import { Users } from './collections/Users'
|
|
||||||
import { Footer } from './Footer/config'
|
import { Footer } from './Footer/config'
|
||||||
import { Header } from './Header/config'
|
import { Header } from './Header/config'
|
||||||
import { plugins } from './plugins'
|
import { plugins } from './plugins'
|
||||||
@@ -18,12 +17,15 @@ import { defaultLexical } from '@/fields/defaultLexical'
|
|||||||
import { getServerSideURL } from './utilities/getURL'
|
import { getServerSideURL } from './utilities/getURL'
|
||||||
import { Papers } from '@/collections/Papers'
|
import { Papers } from '@/collections/Papers'
|
||||||
import { Technologies } from '@/collections/Technologies'
|
import { Technologies } from '@/collections/Technologies'
|
||||||
|
import { authjsPlugin } from 'payload-authjs'
|
||||||
|
import { authConfig } from '@/auth.config'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
admin: {
|
admin: {
|
||||||
|
user: "users",
|
||||||
components: {
|
components: {
|
||||||
// The `BeforeLogin` component renders a message that you see while logging into your admin panel.
|
// The `BeforeLogin` component renders a message that you see while logging into your admin panel.
|
||||||
// Feel free to delete this at any time. Simply remove the line below and the import `BeforeLogin` statement on line 15.
|
// Feel free to delete this at any time. Simply remove the line below and the import `BeforeLogin` statement on line 15.
|
||||||
@@ -35,7 +37,7 @@ export default buildConfig({
|
|||||||
importMap: {
|
importMap: {
|
||||||
baseDir: path.resolve(dirname),
|
baseDir: path.resolve(dirname),
|
||||||
},
|
},
|
||||||
user: Users.slug,
|
|
||||||
livePreview: {
|
livePreview: {
|
||||||
breakpoints: [
|
breakpoints: [
|
||||||
{
|
{
|
||||||
@@ -66,10 +68,13 @@ export default buildConfig({
|
|||||||
url: process.env.DATABASE_URI || '',
|
url: process.env.DATABASE_URI || '',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
collections: [Papers, Technologies, Pages, Posts, Media, Categories, Users],
|
collections: [Papers, Technologies, Pages, Posts, Media, Categories],
|
||||||
cors: [getServerSideURL()].filter(Boolean),
|
cors: [getServerSideURL()].filter(Boolean),
|
||||||
globals: [Header, Footer],
|
globals: [Header, Footer],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
authjsPlugin({
|
||||||
|
authjsConfig: authConfig,
|
||||||
|
}),
|
||||||
...plugins,
|
...plugins,
|
||||||
// storage-adapter-placeholder
|
// storage-adapter-placeholder
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user