File tree Expand file tree Collapse file tree 13 files changed +176
-45
lines changed Expand file tree Collapse file tree 13 files changed +176
-45
lines changed Original file line number Diff line number Diff line change @@ -56,7 +56,8 @@ const config = {
56
56
argsIgnorePattern : '^_'
57
57
}
58
58
] ,
59
- 'unused-imports/no-unused-imports' : 'warn'
59
+ 'unused-imports/no-unused-imports' : 'warn' ,
60
+ 'react/no-unescaped-entities' : 'off'
60
61
} ,
61
62
overrides : [
62
63
{
Original file line number Diff line number Diff line change 1
1
import { ReactNode } from 'react'
2
2
3
- import { redirect } from 'next/navigation '
4
-
3
+ import { Forbidden } from '@/components/Forbidden '
4
+ import { Unauthorized } from '@/components/Unauthorized'
5
5
import { getServerUser } from '@/lib/session'
6
6
7
7
import { AdminLinks } from './AdminLinks'
@@ -14,11 +14,11 @@ export default async function AdminLayout({
14
14
const user = await getServerUser ( )
15
15
16
16
if ( ! user ) {
17
- redirect ( '/login' )
17
+ return < Unauthorized />
18
18
}
19
19
20
20
if ( ! user . admin ) {
21
- redirect ( '/' )
21
+ return < Forbidden />
22
22
}
23
23
24
24
return (
Original file line number Diff line number Diff line change @@ -31,5 +31,14 @@ export const ErrorMessage = () => {
31
31
32
32
const errorMessage = error && ( errors [ error ] ?? errors . default )
33
33
34
- return < > { errorMessage && < p > { errorMessage } </ p > } </ >
34
+ return (
35
+ < >
36
+ { errorMessage && (
37
+ < p className = "text-center" >
38
+ { errorMessage } < br />
39
+ (Code: { error } )
40
+ </ p >
41
+ ) }
42
+ </ >
43
+ )
35
44
}
Load Diff This file was deleted.
Original file line number Diff line number Diff line change 1
1
import { Suspense } from 'react'
2
2
3
+ import { LoginGitHub } from '@/components/Login/GitHub'
4
+ import { LoginGoogle } from '@/components/Login/Google'
5
+
3
6
import { ErrorMessage } from './ErrorMessage'
4
- import { SignIn } from './SignIn'
5
7
6
8
export default function Login ( ) {
7
9
return (
@@ -11,16 +13,15 @@ export default function Login() {
11
13
Continue to PROGRAMMING.IN.TH
12
14
</ h2 >
13
15
</ div >
14
- < div className = "sm:mx-auto sm:w-full sm:max-w-md" >
16
+ < div className = "my-6 sm:mx-auto sm:w-full sm:max-w-md" >
15
17
< Suspense >
16
18
< ErrorMessage />
17
19
</ Suspense >
18
20
</ div >
19
- < div className = "mt-2 px-4 sm:mx-auto sm:w-full sm:max-w-md" >
20
- < div className = "bg-white px-4 py-2 dark:bg-slate-800 sm:rounded-lg sm:px-10" >
21
- < div className = "mt-12 flex flex-col gap-6" >
22
- < SignIn />
23
- </ div >
21
+ < div className = "px-4 sm:mx-auto sm:w-full sm:max-w-md" >
22
+ < div className = "flex flex-col gap-6 bg-white px-4 py-2 dark:bg-slate-800 sm:rounded-lg sm:px-10" >
23
+ < LoginGoogle />
24
+ < LoginGitHub />
24
25
</ div >
25
26
</ div >
26
27
</ div >
Original file line number Diff line number Diff line change
1
+ import { LoginGitHub } from '@/components/Login/GitHub'
2
+ import { LoginGoogle } from '@/components/Login/Google'
3
+ import { Unauthorized } from '@/components/Unauthorized'
4
+ import prisma from '@/lib/prisma'
5
+ import { getServerUser } from '@/lib/session'
6
+
7
+ export default async function User ( ) {
8
+ const user = await getServerUser ( )
9
+
10
+ if ( ! user || ! user . id ) return < Unauthorized />
11
+
12
+ const pUser = await prisma . user . findUniqueOrThrow ( {
13
+ where : {
14
+ id : user . id
15
+ } ,
16
+ include : {
17
+ accounts : true
18
+ }
19
+ } )
20
+
21
+ const linkedToGoogle = pUser . accounts . some (
22
+ account => account . provider === 'google'
23
+ )
24
+
25
+ const linkedToGitHub = pUser . accounts . some (
26
+ account => account . provider === 'github'
27
+ )
28
+
29
+ return (
30
+ < div className = "flex min-h-screen flex-col justify-center gap-4 pb-44 sm:px-6 lg:px-8" >
31
+ < h2 className = "mt-6 px-4 text-center text-3xl font-extrabold text-prog-gray-500 dark:text-prog-gray-100" >
32
+ User Dashboard
33
+ </ h2 >
34
+
35
+ < div className = "px-4 sm:mx-auto sm:w-full sm:max-w-md" >
36
+ < div className = "flex flex-col gap-6 bg-white px-4 py-2 dark:bg-slate-800 sm:rounded-lg sm:px-10" >
37
+ < LoginGoogle type = { linkedToGoogle ? 'linked' : 'link' } />
38
+ < LoginGitHub type = { linkedToGitHub ? 'linked' : 'link' } />
39
+ </ div >
40
+ </ div >
41
+ </ div >
42
+ )
43
+ }
Original file line number Diff line number Diff line change
1
+ export const Forbidden = ( ) => {
2
+ return (
3
+ < div className = "flex min-h-screen flex-col items-center justify-center gap-16 pb-44 sm:px-6 lg:px-8" >
4
+ < div className = "sm:mx-auto sm:w-full sm:max-w-md" >
5
+ < h2 className = "mt-6 px-4 text-center text-3xl font-extrabold text-prog-gray-500 dark:text-prog-gray-100" >
6
+ Forbidden, you don't have access
7
+ </ h2 >
8
+ </ div >
9
+
10
+ < a
11
+ href = "https://youtu.be/dQw4w9WgXcQ"
12
+ className = "w-fit rounded-md bg-prog-primary-500 px-6 py-4 text-center text-2xl font-medium text-white shadow-md transition-colors hover:bg-prog-primary-600"
13
+ >
14
+ Get access
15
+ </ a >
16
+ </ div >
17
+ )
18
+ }
Original file line number Diff line number Diff line change
1
+ 'use client'
2
+
3
+ import { signIn } from 'next-auth/react'
4
+
5
+ import { AuthGitHubLogo } from '@/svg/Socials'
6
+
7
+ import { LoginProps , getProps } from './props'
8
+ import styles from './style.module.css'
9
+
10
+ export const LoginGitHub = ( { type } : LoginProps ) => {
11
+ const { message, disabled } = getProps ( 'GitHub' , type )
12
+
13
+ return (
14
+ < button
15
+ className = { styles . loginButton }
16
+ onClick = { ( ) => signIn ( 'github' ) }
17
+ disabled = { disabled }
18
+ >
19
+ < AuthGitHubLogo className = "h-5 w-5" />
20
+ < span > { message } </ span >
21
+ </ button >
22
+ )
23
+ }
Original file line number Diff line number Diff line change
1
+ 'use client'
2
+
3
+ import { signIn } from 'next-auth/react'
4
+
5
+ import { AuthGoogleLogo } from '@/svg/Socials'
6
+
7
+ import { LoginProps , getProps } from './props'
8
+ import styles from './style.module.css'
9
+
10
+ export const LoginGoogle = ( { type } : LoginProps ) => {
11
+ const { message, disabled } = getProps ( 'Google' , type )
12
+
13
+ return (
14
+ < button
15
+ className = { styles . loginButton }
16
+ onClick = { ( ) => signIn ( 'google' ) }
17
+ disabled = { disabled }
18
+ >
19
+ < AuthGoogleLogo className = "h-5 w-5" />
20
+ < span > { message } </ span >
21
+ </ button >
22
+ )
23
+ }
Original file line number Diff line number Diff line change
1
+ type SignInType = 'signIn' | 'linked' | 'link'
2
+
3
+ export type LoginProps = {
4
+ type ?: SignInType
5
+ }
6
+
7
+ export function getProps ( providerName : string , type : SignInType = 'signIn' ) {
8
+ const message =
9
+ type === 'signIn'
10
+ ? `Sign in with ${ providerName } `
11
+ : type === 'linked'
12
+ ? 'Account Linked'
13
+ : `Link ${ providerName } account`
14
+
15
+ const disabled = type === 'linked'
16
+
17
+ return { message, disabled }
18
+ }
Original file line number Diff line number Diff line change
1
+ .loginButton {
2
+ @apply inline-flex w-full justify-center gap-3 rounded-md px-4 py-4 text-sm font-medium shadow-md transition disabled:cursor-not-allowed;
3
+ @apply bg-white text-gray-500 enabled:hover:bg-gray-50;
4
+ @apply dark:bg-slate-600 dark:text-gray-200 enabled:dark:hover:bg-slate-700;
5
+ }
Original file line number Diff line number Diff line change
1
+ import Link from 'next/link'
2
+
3
+ export const Unauthorized = ( ) => {
4
+ return (
5
+ < div className = "flex min-h-screen flex-col items-center justify-center gap-16 pb-44 sm:px-6 lg:px-8" >
6
+ < div className = "sm:mx-auto sm:w-full sm:max-w-md" >
7
+ < h2 className = "mt-6 px-4 text-center text-3xl font-extrabold text-prog-gray-500 dark:text-prog-gray-100" >
8
+ Unauthorized, please log in
9
+ </ h2 >
10
+ </ div >
11
+
12
+ < Link
13
+ href = "/login"
14
+ className = "w-fit rounded-md bg-prog-primary-500 px-6 py-4 text-center text-2xl font-medium text-white shadow-md transition-colors hover:bg-prog-primary-600"
15
+ >
16
+ Login
17
+ </ Link >
18
+ </ div >
19
+ )
20
+ }
Original file line number Diff line number Diff line change 10
10
! process . env . GITHUB_SECRET ||
11
11
! process . env . GOOGLE_CLIENT_ID ||
12
12
! process . env . GOOGLE_CLIENT_SECRET
13
- )
13
+ ) {
14
14
throw new Error ( 'Failed to initialize authentication' )
15
+ }
15
16
16
17
export const authOptions : NextAuthOptions = {
17
18
adapter : PrismaAdapter ( prisma ) ,
You can’t perform that action at this time.
0 commit comments