Skip to content

Commit 787c7e7

Browse files
committed
fix: if access hidden note when loggin
Signed-off-by: Innei <[email protected]>
1 parent 158f30b commit 787c7e7

File tree

17 files changed

+118
-70
lines changed

17 files changed

+118
-70
lines changed

next.config.mjs

+6-5
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ if (repoInfo) {
2323
/** @type {import('next').NextConfig} */
2424
// eslint-disable-next-line import/no-mutable-exports
2525
let nextConfig = {
26-
logging: {
27-
fetches: {
28-
fullUrl: true,
29-
},
30-
},
26+
// logging: {
27+
// fetches: {
28+
29+
// // fullUrl: true,
30+
// },
31+
// },
3132
env: {
3233
APP_VERSION: pkg.version,
3334
COMMIT_HASH: commitHash,

src/app/(app)/(note-topic)/notes/(topic-detail)/topics/[slug]/layout.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Metadata } from 'next'
33

44
import { QueryHydrate } from '~/components/common/QueryHydrate'
55
import { NormalContainer } from '~/components/layout/container/Normal'
6-
import { attachUAAndRealIp } from '~/lib/attach-ua'
6+
import { attachServerFetch } from '~/lib/attach-ua'
77
import { isShallowEqualArray } from '~/lib/lodash'
88
import { getQueryClient } from '~/lib/query-client.server'
99
import { definePrerenderPage } from '~/lib/request.server'
@@ -16,7 +16,7 @@ export const generateMetadata = async (
1616
slug: string
1717
}>,
1818
) => {
19-
attachUAAndRealIp()
19+
attachServerFetch()
2020
const queryClient = getQueryClient()
2121

2222
const query = getTopicQuery(props.params.slug)

src/app/(app)/(page-detail)/[slug]/layout.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
BottomToUpTransitionView,
1515
} from '~/components/ui/transition'
1616
import { OnlyMobile } from '~/components/ui/viewport/OnlyMobile'
17-
import { attachUAAndRealIp } from '~/lib/attach-ua'
17+
import { attachServerFetch } from '~/lib/attach-ua'
1818
import { getOgUrl } from '~/lib/helper.server'
1919
import { getSummaryFromMd } from '~/lib/markdown'
2020
import { apiClient } from '~/lib/request'
@@ -33,7 +33,7 @@ import {
3333

3434
export const dynamic = 'force-dynamic'
3535
const getData = cache(async (params: PageParams) => {
36-
attachUAAndRealIp()
36+
attachServerFetch()
3737
const data = await apiClient.page
3838
.getBySlug(params.slug)
3939
.catch(requestErrorHandler)

src/app/(app)/api.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import type { AggregateRoot } from '@mx-space/api-client'
55
import { simpleCamelcaseKeys } from '@mx-space/api-client'
66

77
import { appStaticConfig } from '~/app.static.config'
8-
import { attachUAAndRealIp } from '~/lib/attach-ua'
8+
import { attachServerFetch } from '~/lib/attach-ua'
99
import { getQueryClient } from '~/lib/query-client.server'
1010
import { apiClient } from '~/lib/request'
1111

1212
const cacheTime = appStaticConfig.cache.enabled
1313
? appStaticConfig.cache.ttl.aggregation
1414
: 1
1515
export const fetchAggregationData = cache(async () => {
16-
attachUAAndRealIp()
16+
attachServerFetch()
1717
const queryClient = getQueryClient()
1818
const fetcher = async () =>
1919
(await $fetch<

src/app/(app)/categories/[slug]/api.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { cache } from 'react'
22

3-
import { attachUAAndRealIp } from '~/lib/attach-ua'
3+
import { attachServerFetch } from '~/lib/attach-ua'
44
import { apiClient } from '~/lib/request'
55
import { requestErrorHandler } from '~/lib/request.server'
66

77
export const getData = cache(async (params: { slug: string }) => {
8-
attachUAAndRealIp()
8+
attachServerFetch()
99
return await apiClient.category
1010
.getCategoryByIdOrSlug(params.slug)
1111
.catch(requestErrorHandler)

src/app/(app)/notes/[id]/api.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ import { cache } from 'react'
22
import { headers } from 'next/dist/client/components/headers'
33

44
import { REQUEST_QUERY } from '~/constants/system'
5-
import { attachUAAndRealIp } from '~/lib/attach-ua'
5+
import { attachServerFetch } from '~/lib/attach-ua'
66
import { getQueryClient } from '~/lib/query-client.server'
77
import { requestErrorHandler } from '~/lib/request.server'
88
import { queries } from '~/queries/definition'
99

1010
export const getData = cache(async (params: { id: string }) => {
11-
attachUAAndRealIp()
11+
attachServerFetch()
12+
1213
const header = headers()
1314
const searchParams = new URLSearchParams(header.get(REQUEST_QUERY) || '')
1415
const id = params.id
16+
const token = searchParams.get('token')
1517
const query = queries.note.byNid(
1618
id,
1719
searchParams.get('password') || undefined,
20+
token ? `${token}` : undefined,
1821
)
1922
const data = await getQueryClient()
2023
.fetchQuery(query)

src/app/(app)/notes/[id]/page.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import {
1212
NoteMetaReadingCount,
1313
NoteTopic,
1414
} from '~/components/modules/note'
15-
import { NoteRootBanner } from '~/components/modules/note/NoteBanner'
15+
import {
16+
NoteBanner,
17+
NoteRootBanner,
18+
} from '~/components/modules/note/NoteBanner'
1619
import { ArticleRightAside } from '~/components/modules/shared/ArticleRightAside'
1720
import { BanCopyWrapper } from '~/components/modules/shared/BanCopyWrapper'
1821
import { ReadIndicatorForMobile } from '~/components/modules/shared/ReadIndicator'
@@ -59,6 +62,12 @@ export default async function Page(props: {
5962
</ClientOnly>
6063
</span>
6164
<NoteRootBanner />
65+
{data.hide && (
66+
<NoteBanner
67+
type="warning"
68+
message="这篇文章是非公开的,仅登录可见"
69+
/>
70+
)}
6271
</header>
6372

6473
<NoteHideIfSecret>

src/app/(app)/notes/page.tsx

+21-30
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,24 @@
1-
'use client'
1+
import { cookies } from 'next/headers'
2+
import { redirect } from 'next/navigation'
23

3-
import { useQuery } from '@tanstack/react-query'
4-
import { useEffect } from 'react'
5-
import { useRouter } from 'next/navigation'
6-
7-
import { FullPageLoading } from '~/components/ui/loading'
4+
import { attachServerFetchAuth, detachServerFetchAuth } from '~/lib/attach-ua'
5+
import { AuthKeyNames } from '~/lib/cookie'
86
import { apiClient } from '~/lib/request'
7+
import { definePrerenderPage } from '~/lib/request.server'
98

10-
export default function Page() {
11-
const {
12-
data: nid,
13-
isError,
14-
isLoading,
15-
} = useQuery({
16-
queryFn: async () => {
17-
return apiClient.note.getLatest()
18-
},
19-
queryKey: ['note-latest'],
20-
select(data) {
21-
return data.data.nid
22-
},
23-
})
24-
25-
const router = useRouter()
26-
useEffect(() => {
27-
if (!nid) return
28-
29-
router.replace(`/notes/${nid}`)
30-
}, [nid, router])
31-
32-
return <FullPageLoading />
33-
}
9+
export default definePrerenderPage()({
10+
async fetcher() {
11+
attachServerFetchAuth()
12+
const { data } = await apiClient.note.getLatest()
13+
detachServerFetchAuth()
14+
return data
15+
},
16+
Component: ({ data: { nid, hide } }) => {
17+
const jwt = cookies().get(AuthKeyNames[0])?.value
18+
if (hide) {
19+
return redirect(`/notes/${nid}?token=${jwt}`)
20+
} else {
21+
redirect(`/notes/${nid}`)
22+
}
23+
},
24+
})

src/app/(app)/posts/(post-detail)/[category]/[slug]/api.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { cache } from 'react'
22

3-
import { attachUAAndRealIp } from '~/lib/attach-ua'
3+
import { attachServerFetch } from '~/lib/attach-ua'
44
import { getQueryClient } from '~/lib/query-client.server'
55
import { requestErrorHandler } from '~/lib/request.server'
66
import { queries } from '~/queries/definition'
@@ -11,7 +11,7 @@ export interface PageParams {
1111
}
1212
export const getData = cache(async (params: PageParams) => {
1313
const { category, slug } = params
14-
attachUAAndRealIp()
14+
attachServerFetch()
1515
const data = await getQueryClient()
1616
.fetchQuery(queries.post.bySlug(category, slug))
1717
.catch(requestErrorHandler)

src/app/(app)/timeline/layout.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { TimelineType } from '@mx-space/api-client'
77
import { QueryHydrate } from '~/components/common/QueryHydrate'
88
import { SearchFAB } from '~/components/modules/shared/SearchFAB'
99
import { REQUEST_QUERY } from '~/constants/system'
10-
import { attachUAAndRealIp } from '~/lib/attach-ua'
10+
import { attachServerFetch } from '~/lib/attach-ua'
1111
import { getQueryClient } from '~/lib/query-client.server'
1212
import { apiClient } from '~/lib/request'
1313

@@ -16,7 +16,7 @@ export const metadata = {
1616
}
1717
export const dynamic = 'force-dynamic'
1818
export default async (props: PropsWithChildren) => {
19-
attachUAAndRealIp()
19+
attachServerFetch()
2020
const header = headers()
2121
const query = header.get(REQUEST_QUERY)
2222

src/components/modules/note/NoteBanner.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const useNoteBanner = () => {
1717
const meta = useCurrentNoteDataSelector((n) => n?.data.meta)
1818

1919
let banner = meta?.banner as {
20-
type: string
20+
type: keyof typeof bannerClassNames
2121
message: string
2222
className: string
2323
style?: any
@@ -31,7 +31,7 @@ const useNoteBanner = () => {
3131
type: 'info',
3232
message: banner,
3333
className: bannerClassNames.info,
34-
}
34+
} as any
3535
}
3636
banner = { ...banner }
3737
banner.type ??= 'info'
@@ -47,20 +47,28 @@ export const NoteRootBanner = () => {
4747
if (!banner) return null
4848

4949
return (
50-
<div className="mx-[var(--padding-h)] mb-4 mt-8 text-sm">
50+
<div className="mx-[var(--padding-h)] mb-4 mt-8">
5151
<NoteBanner {...banner} />
5252
</div>
5353
)
5454
}
5555

5656
export const NoteBanner: FC<{
5757
style?: any
58-
className: string
58+
className?: string
5959
message: string
60+
type?: keyof typeof bannerClassNames
6061
}> = (banner) => {
6162
return (
6263
<div
63-
className={clsxm('flex justify-center p-4 leading-8', banner.className)}
64+
className={clsxm(
65+
'mt-4 flex justify-center p-4 text-base leading-8',
66+
'lg:-ml-12 lg:w-[calc(100%+6rem)]',
67+
'-ml-4 w-[calc(100%+2rem)]',
68+
69+
bannerClassNames[banner.type as keyof typeof bannerClassNames],
70+
banner.className,
71+
)}
6472
style={banner.style}
6573
>
6674
{banner.message}

src/lib/attach-ua.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { headers } from 'next/headers'
1+
import { cookies, headers } from 'next/headers'
22

33
import PKG from '../../package.json'
4+
import { AuthKeyNames } from './cookie'
45
import { attachFetchHeader } from './request'
56

6-
export const attachUAAndRealIp = () => {
7+
export const attachServerFetch = () => {
78
const { get } = headers()
89

910
const ua = get('user-agent')
@@ -22,3 +23,18 @@ export const attachUAAndRealIp = () => {
2223
`${ua} NextJS/v${PKG.dependencies.next} ${PKG.name}/${PKG.version}`,
2324
)
2425
}
26+
27+
export const attachServerFetchAuth = () => {
28+
const cookie = cookies()
29+
const jwt = cookie.get(AuthKeyNames[0])
30+
31+
if (jwt) {
32+
attachFetchHeader('Authorization', `Bearer ${jwt.value}`)
33+
} else {
34+
attachFetchHeader('Authorization', '')
35+
}
36+
}
37+
38+
export const detachServerFetchAuth = () => {
39+
attachFetchHeader('Authorization', null)
40+
}

src/lib/cookie.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import dayjs from 'dayjs'
22
import Cookies from 'js-cookie'
33

4-
export const TokenKey = 'mx-token'
4+
const TokenKey = 'mx-token'
5+
6+
const ClerkCookieKey = '__session'
7+
export const AuthKeyNames = [TokenKey, ClerkCookieKey]
58

69
export function getToken(): string | null {
710
// FUCK clerk constants not export, and mark it internal and can not custom
811
// packages/backend/src/constants.ts
9-
const clerkJwt = Cookies.get('__session')
12+
const clerkJwt = Cookies.get(ClerkCookieKey)
1013

1114
const token = Cookies.get(TokenKey) || clerkJwt
1215

src/lib/define-metadata.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { Metadata } from 'next'
66
import { getQueryClient } from '~/lib/query-client.server'
77
import { queries } from '~/queries/definition'
88

9-
import { attachUAAndRealIp } from './attach-ua'
9+
import { attachServerFetch } from './attach-ua'
1010

1111
export const defineMetadata = <T extends Record<string, string>>(
1212
fn: (
@@ -17,7 +17,7 @@ export const defineMetadata = <T extends Record<string, string>>(
1717
const handler = async ({ params }: { params: T }): Promise<Metadata> => {
1818
const getData = async () => {
1919
const queryClient = getQueryClient()
20-
attachUAAndRealIp()
20+
attachServerFetch()
2121
return await queryClient.fetchQuery({
2222
...queries.aggregation.root(),
2323
})

src/lib/request.server.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { RequestError } from '@mx-space/api-client'
99
import { BizErrorPage } from '~/components/common/BizErrorPage'
1010
import { NormalContainer } from '~/components/layout/container/Normal'
1111

12-
import { attachUAAndRealIp } from './attach-ua'
12+
import { attachServerFetch } from './attach-ua'
1313
import { getErrorMessageFromRequestError } from './request.shared'
1414

1515
export const requestErrorHandler = (error: Error | RequestError) => {
@@ -61,7 +61,7 @@ export const definePrerenderPage =
6161
return async (props: any) => {
6262
const { params, searchParams } = props as NextPageParams<Params, any>
6363
try {
64-
attachUAAndRealIp()
64+
attachServerFetch()
6565
const data = await fetcher({
6666
...params,
6767
...searchParams,

src/lib/request.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const $fetch = createFetch({
3232
if (token) {
3333
headers['Authorization'] = `bearer ${token}`
3434
}
35+
3536
headers['x-session-uuid'] =
3637
globalThis?.sessionStorage?.getItem(uuidStorageKey) ?? uuid
3738

@@ -100,9 +101,13 @@ export const apiClient = createClient(fetchAdapter)(API_URL, {
100101
},
101102
})
102103

103-
export const attachFetchHeader = (key: string, value: string) => {
104+
export const attachFetchHeader = (key: string, value: string | null) => {
104105
const original = globalConfigureHeader[key]
105-
globalConfigureHeader[key] = value
106+
if (value === null) {
107+
delete globalConfigureHeader[key]
108+
} else {
109+
globalConfigureHeader[key] = value
110+
}
106111

107112
return () => {
108113
if (typeof original === 'undefined') {

0 commit comments

Comments
 (0)