From 6db037204c0d11abf9dcf407b2260143a6aa51a0 Mon Sep 17 00:00:00 2001
From: luorijun
Date: Sat, 26 Apr 2025 14:18:08 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=89=B4=E6=9D=83=E9=80=BB?=
=?UTF-8?q?=E8=BE=91=EF=BC=8C=E6=96=B0=E5=A2=9E=E4=B8=AD=E9=97=B4=E4=BB=B6?=
=?UTF-8?q?=E5=88=B7=E6=96=B0=E4=BB=A4=E7=89=8C=EF=BC=8C=E6=8E=88=E6=9D=83?=
=?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=BB=9F=E4=B8=80=E5=90=8E=E5=A4=84=E7=90=86?=
=?UTF-8?q?=E6=97=A0=E6=8E=88=E6=9D=83=E8=B7=B3=E8=BD=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +
src/actions/{auth => }/auth.ts | 84 +++---
src/actions/auth/identify.ts | 22 --
src/actions/base.ts | 310 ++++++++-------------
src/actions/user.ts | 22 +-
src/actions/{auth => }/verify.ts | 17 +-
src/app/(api)/identify/callback/page.tsx | 2 +-
src/app/(auth)/login/page.tsx | 6 +-
src/app/admin/(dashboard)/page.tsx | 4 +-
src/app/admin/_client/navbar.tsx | 34 +--
src/app/admin/_client/profile.tsx | 2 +-
src/app/admin/identify/page.tsx | 2 +-
src/app/admin/layout.tsx | 20 +-
src/app/layout.tsx | 14 +-
src/app/test/route.ts | 14 +
src/assets/logo-avatar.svg | 17 ++
src/components/providers/StoreProvider.tsx | 4 +-
src/lib/api.ts | 2 -
src/middleware.ts | 38 +++
src/stores/profile.ts | 5 +-
20 files changed, 303 insertions(+), 318 deletions(-)
rename src/actions/{auth => }/auth.ts (55%)
delete mode 100644 src/actions/auth/identify.ts
rename src/actions/{auth => }/verify.ts (81%)
create mode 100644 src/app/test/route.ts
create mode 100644 src/assets/logo-avatar.svg
create mode 100644 src/middleware.ts
diff --git a/README.md b/README.md
index d5e6de9..068f17b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
## TODO
+
+
使用 pure js 的包代替 canvas,加快编译速度
提取后刷新提取页套餐可用余量
diff --git a/src/actions/auth/auth.ts b/src/actions/auth.ts
similarity index 55%
rename from src/actions/auth/auth.ts
rename to src/actions/auth.ts
index 466beb7..6d14805 100644
--- a/src/actions/auth/auth.ts
+++ b/src/actions/auth.ts
@@ -1,19 +1,10 @@
'use server'
import {cookies} from 'next/headers'
import {ApiResponse, UnauthorizedError} from '@/lib/api'
-import {AuthContext} from '@/lib/auth'
import {User} from '@/lib/models'
-import {callByDevice, callByUser, callPublic, getUserToken} from '@/actions/base'
-import {redirect} from 'next/navigation'
-import {cache} from 'react'
+import {callByDevice, callByUser} from '@/actions/base'
-export interface LoginParams {
- username: string
- password: string
- remember: boolean
-}
-
-type LoginResp = {
+type TokenResp = {
access_token: string
refresh_token: string
expires_in: number
@@ -21,9 +12,14 @@ type LoginResp = {
scope?: string
}
-export async function login(props: LoginParams): Promise {
+export async function login(props: {
+ username: string
+ password: string
+ remember: boolean
+}): Promise {
+
// 尝试登录
- const result = await callByDevice('/api/auth/token', {
+ const result = await callByDevice('/api/auth/token', {
...props,
grant_type: 'password',
login_type: 'phone_code',
@@ -44,14 +40,6 @@ export async function login(props: LoginParams): Promise {
httpOnly: true,
sameSite: 'strict',
})
- // cookieStore.set('auth_info', JSON.stringify(data.auth), {
- // httpOnly: true,
- // sameSite: 'strict',
- // })
- // cookieStore.set('auth_profile', JSON.stringify(data.profile), {
- // httpOnly: true,
- // sameSite: 'strict',
- // })
return {
success: true,
@@ -91,19 +79,49 @@ export async function logout() {
}
export async function getProfile() {
- try {
- const token = await getUserToken()
- const result = await callPublic('/api/user/get/token', {token})
+ return await callByUser('/api/auth/introspect')
+}
- if (!result.success) {
- throw new Error('获取用户信息失败')
- }
- return result.data
+export async function refreshAuth() {
+ const cookie = await cookies()
+
+ const userRefresh = cookie.get('auth_refresh')?.value
+ if (!userRefresh) {
+ throw UnauthorizedError
}
- catch (e) {
- if (e === UnauthorizedError) {
- return null
- }
- throw e
+
+ // 请求刷新访问令牌
+ const resp = await callByDevice(`/api/auth/token`, {
+ grant_type: 'refresh_token',
+ refresh_token: userRefresh,
+ })
+
+ // 处理请求
+ if (!resp.success) {
+ cookie.delete('auth_refresh')
+ throw UnauthorizedError
+ }
+
+ // 解析响应
+ const data = resp.data
+ const nextAccessToken = data.access_token
+ const nextRefreshToken = data.refresh_token
+ const expiresIn = data.expires_in
+
+ // 保存令牌到 cookies
+ cookie.set('auth_token', nextAccessToken, {
+ httpOnly: true,
+ sameSite: 'strict',
+ maxAge: Math.max(expiresIn, 0),
+ })
+ cookie.set('auth_refresh', nextRefreshToken, {
+ httpOnly: true,
+ sameSite: 'strict',
+ })
+
+ // 返回新的访问令牌
+ return {
+ access_token: nextAccessToken,
+ refresh_token: nextRefreshToken,
}
}
diff --git a/src/actions/auth/identify.ts b/src/actions/auth/identify.ts
deleted file mode 100644
index 52f7b2b..0000000
--- a/src/actions/auth/identify.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-'use server'
-import {callByUser, callPublic} from '@/actions/base'
-
-export async function Identify(props: {
- type: number
- name: string
- iden_no: string
-}) {
- return await callByUser<{
- identified: boolean
- target: string
- }>('/api/user/identify', props)
-}
-
-export async function IdentifyCallback(props: {
- id: string
-}) {
- return await callPublic<{
- success: boolean
- message: string
- }>('/api/user/identify/callback', props)
-}
diff --git a/src/actions/base.ts b/src/actions/base.ts
index d03bcfe..8b408d4 100644
--- a/src/actions/base.ts
+++ b/src/actions/base.ts
@@ -1,184 +1,13 @@
'use server'
-import {API_BASE_URL, CLIENT_ID, CLIENT_SECRET, ApiResponse, UnauthorizedError} from '@/lib/api'
+import {API_BASE_URL, ApiResponse, CLIENT_ID, CLIENT_SECRET} from '@/lib/api'
import {cookies, headers} from 'next/headers'
-import {redirect} from 'next/navigation'
import {cache} from 'react'
+import {redirect} from 'next/navigation'
// ======================
-// region device token
+// public
// ======================
-async function callByDevice(
- endpoint: string,
- data: unknown,
-): Promise> {
- return _callByDevice(endpoint, data ? JSON.stringify(data) : undefined)
-}
-
-// 通用的API调用函数
-const _callByDevice = cache(async (
- endpoint: string,
- data?: string,
-): Promise> => {
- try {
- // 获取设备令牌
- if (!CLIENT_ID || !CLIENT_SECRET) {
- throw new Error('缺少CLIENT_ID或CLIENT_SECRET环境变量')
- }
- const token = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64url')
-
- // 构造请求
- const url = `${API_BASE_URL}${endpoint}`
- const request = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Basic ${token}`,
- },
- body: data,
- }
-
- // 发送请求
- const response = await fetch(`${API_BASE_URL}${endpoint}`, request)
-
- // 检查响应状态
- return handleResponse(response)
- }
- catch (e) {
- throw new Error('服务调用失败', {cause: e})
- }
-})
-
-// endregion
-
-// ======================
-// region user token
-// ======================
-
-async function getUserToken(refresh = false): Promise {
- // 从 cookie 中获取用户令牌
- const cookie = await cookies()
- const userToken = cookie.get('auth_token')?.value
- const userRefresh = cookie.get('auth_refresh')?.value
-
- // 检查缓存的令牌是否可用
- if (!refresh && userToken) {
- return userToken
- }
-
- // 如果没有刷新令牌,抛出异常
- if (!userRefresh) {
- throw UnauthorizedError
- }
-
- // 请求刷新访问令牌
- const addr = `${API_BASE_URL}/api/auth/token`
- const body = {
- grant_type: 'refresh_token',
- client_id: CLIENT_ID,
- client_secret: CLIENT_SECRET,
- refresh_token: userRefresh,
- }
-
- const response = await fetch(addr, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(body),
- })
-
- if (!response.ok) {
- console.log('刷新令牌失败', `status=${response.status}`, await response.text())
- throw UnauthorizedError
- }
-
- // 保存新的用户令牌到 cookie
- const data = await response.json()
- const nextAccessToken = data.access_token
- const nextRefreshToken = data.refresh_token
- const expiresIn = data.expires_in
-
- cookie.set('auth_token', nextAccessToken, {
- httpOnly: true,
- sameSite: 'strict',
- maxAge: Math.max(expiresIn, 0),
- })
- cookie.set('auth_refresh', nextRefreshToken, {
- httpOnly: true,
- sameSite: 'strict',
- maxAge: 7 * 24 * 3600, // 7天
- })
-
- return nextAccessToken
-}
-
-// 使用用户令牌的API调用函数
-async function callByUser(
- endpoint: string,
- data?: unknown,
-): Promise> {
- return _callByUser(endpoint, data ? JSON.stringify(data) : undefined)
-}
-
-const _callByUser = cache(async (
- endpoint: string,
- data?: string,
-): Promise> => {
- const header = await headers()
- try {
- let token = await getUserToken()
-
- // 构造请求
- const request = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${token}`,
- } as Record,
- body: data,
- }
-
- const userIp = header.get('x-forwarded-for')
- if (userIp) {
- request.headers['X-Forwarded-For'] = userIp
- }
-
- // 发送请求
- let response = await fetch(`${API_BASE_URL}${endpoint}`, request)
- if (response.status === 401) {
- token = await getUserToken(true)
- request.headers['Authorization'] = `Bearer ${token}`
- response = await fetch(`${API_BASE_URL}${endpoint}`, request)
- }
-
- if (response.status === 401) {
- throw UnauthorizedError
- }
-
- return handleResponse(response)
- }
- catch (e) {
- if (e === UnauthorizedError) {
- const referer = header.get('referer')
- let redirectUrl = '/login'
- if (referer) {
- const url = new URL(referer)
- redirectUrl = `/login?redirect=${encodeURIComponent(url.pathname)}`
- }
- return redirect(redirectUrl)
- }
- throw new Error('服务调用失败', {cause: e})
- }
-})
-
-// endregion
-
-// ======================
-// region no token
-// ======================
-
-// 不需要令牌的公共API调用函数
async function callPublic(
endpoint: string,
data?: unknown,
@@ -190,33 +19,106 @@ const _callPublic = cache(async (
endpoint: string,
data?: string,
): Promise> => {
- try {
- const url = `${API_BASE_URL}${endpoint}`
- const request: RequestInit = {
+ return call(`${API_BASE_URL}${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: data,
- }
-
- const response = await fetch(url, request)
- return handleResponse(response)
- }
- catch (e) {
- throw new Error('服务调用失败', {cause: e})
- }
+ },
+ )
})
-// endregion
+// ======================
+// device
+// ======================
-// 统一响应解析
-async function handleResponse(response: Response): Promise> {
+async function callByDevice(
+ endpoint: string,
+ data: unknown,
+): Promise> {
+ return _callByDevice(endpoint, data ? JSON.stringify(data) : undefined)
+}
+
+const _callByDevice = cache(async (
+ endpoint: string,
+ data?: string,
+): Promise> => {
+
+ // 获取设备令牌
+ if (!CLIENT_ID || !CLIENT_SECRET) {
+ return {
+ success: false,
+ status: 401,
+ message: '未配置 CLIENT_ID 或 CLIENT_SECRET',
+ }
+ }
+ const token = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64url')
+
+ // 发起请求
+ return call(`${API_BASE_URL}${endpoint}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Basic ${token}`,
+ },
+ body: data,
+ })
+})
+
+// ======================
+// user
+// ======================
+
+async function callByUser(
+ endpoint: string,
+ data?: unknown,
+): Promise> {
+ return postCall(_callByUser(endpoint, data ? JSON.stringify(data) : undefined))
+}
+
+const _callByUser = cache(async (
+ endpoint: string,
+ data?: string,
+): Promise> => {
+ const header = await headers()
+
+ // 获取用户令牌
+ const cookie = await cookies()
+ const token = cookie.get('auth_token')?.value
+ if (!token) {
+ return {
+ success: false,
+ status: 401,
+ message: '会话已失效',
+ }
+ }
+
+ // 发起请求
+ return await call(`${API_BASE_URL}${endpoint}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`,
+ 'X-Forwarded-For': header.get('x-forwarded-for') || '[web]unknown',
+ 'User-Agent': header.get('user-agent') || '[web]unknown',
+ } as Record,
+ body: data,
+ })
+})
+
+
+// ======================
+// call
+// ======================
+
+async function call(url: string, request: RequestInit): Promise> {
+ const response = await fetch(url, request)
const type = response.headers.get('Content-Type') ?? 'text/plain'
if (type.indexOf('application/json') !== -1) {
const json = await response.json()
if (!response.ok) {
- console.log('响应不成功', `status=${response.status}`, json)
+ console.log('后端请求失败', url, `status=${response.status}`, json)
return {
success: false,
status: response.status,
@@ -231,7 +133,7 @@ async function handleResponse(response: Response): Promise(response: Response): Promise(rawResp: Promise>) {
+ const header = await headers()
+ const pathname = header.get('x-pathname') || '/'
+ const resp = await rawResp
+
+ // 重定向到登录页
+ const match = [
+ RegExp(`^/admin.*`),
+ ].some(item => item.test(pathname))
+
+ if (match && !resp.success && resp.status === 401) {
+ redirect(pathname === '/' ? '/login' : `/login?redirect=${pathname}`)
+ }
+
+ return resp
+}
// 导出
export {
- getUserToken,
+ callPublic,
callByDevice,
callByUser,
- callPublic,
}
diff --git a/src/actions/user.ts b/src/actions/user.ts
index f10a630..81cb59b 100644
--- a/src/actions/user.ts
+++ b/src/actions/user.ts
@@ -1,6 +1,6 @@
'use server'
-import {callByUser} from '@/actions/base'
+import {callByUser, callPublic} from '@/actions/base'
export async function RechargeByAlipay(props: {
amount: number
@@ -31,3 +31,23 @@ export async function RechargeByWechatConfirm(props: {
}) {
return callByUser('/api/user/recharge/confirm/wechat', props)
}
+
+export async function Identify(props: {
+ type: number
+ name: string
+ iden_no: string
+}) {
+ return await callByUser<{
+ identified: boolean
+ target: string
+ }>('/api/user/identify', props)
+}
+
+export async function IdentifyCallback(props: {
+ id: string
+}) {
+ return await callPublic<{
+ success: boolean
+ message: string
+ }>('/api/user/identify/callback', props)
+}
diff --git a/src/actions/auth/verify.ts b/src/actions/verify.ts
similarity index 81%
rename from src/actions/auth/verify.ts
rename to src/actions/verify.ts
index bbe456e..d6e53af 100644
--- a/src/actions/auth/verify.ts
+++ b/src/actions/verify.ts
@@ -1,16 +1,13 @@
'use server'
+import {ApiResponse} from '@/lib/api'
+import {callByDevice} from '@/actions/base'
import {cookies} from 'next/headers'
import crypto from 'crypto'
-import {ApiResponse} from '@/lib/api'
-import { callByDevice } from '@/actions/base'
-
-export interface VerifyParams {
+export async function sendSMS(props: {
phone: string
- captcha: string // 添加验证码字段
-}
-
-export default async function verify(props: VerifyParams): Promise {
+ captcha: string
+}): Promise {
try {
// 人机验证
if (!props.captcha?.length) {
@@ -20,7 +17,7 @@ export default async function verify(props: VerifyParams): Promise
message: '请输入验证码',
}
}
- const valid = await verifyCaptcha(props.captcha)
+ const valid = await checkCaptcha(props.captcha)
if (!valid) {
return {
success: false,
@@ -41,7 +38,7 @@ export default async function verify(props: VerifyParams): Promise
}
}
-async function verifyCaptcha(userInput: string): Promise {
+export async function checkCaptcha(userInput: string): Promise {
const cookieStore = await cookies()
const hash = cookieStore.get('captcha_hash')?.value
const salt = cookieStore.get('captcha_salt')?.value
diff --git a/src/app/(api)/identify/callback/page.tsx b/src/app/(api)/identify/callback/page.tsx
index b5d933b..0848c91 100644
--- a/src/app/(api)/identify/callback/page.tsx
+++ b/src/app/(api)/identify/callback/page.tsx
@@ -1,7 +1,7 @@
'use client'
import {Suspense, useEffect, useState} from 'react'
import {useSearchParams} from 'next/navigation'
-import {IdentifyCallback} from '@/actions/auth/identify'
+import {IdentifyCallback} from '@/actions/user'
import {Card, CardContent} from '@/components/ui/card'
import {CheckCircle, AlertCircle, Loader2} from 'lucide-react'
diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx
index 039a3c4..af93267 100644
--- a/src/app/(auth)/login/page.tsx
+++ b/src/app/(auth)/login/page.tsx
@@ -19,8 +19,8 @@ import {zodResolver} from '@hookform/resolvers/zod'
import {useForm} from 'react-hook-form'
import zod from 'zod'
import Captcha from './captcha'
-import verify from '@/actions/auth/verify'
-import {login} from '@/actions/auth/auth'
+import {login} from '@/actions/auth'
+import {sendSMS} from '@/actions/verify'
import {useRouter, useSearchParams} from 'next/navigation'
import {toast} from 'sonner'
import {ApiResponse} from '@/lib/api'
@@ -83,7 +83,7 @@ export default function LoginPage(props: LoginPageProps) {
// 发送验证码
let resp: ApiResponse
try {
- resp = await verify({
+ resp = await sendSMS({
phone: username,
captcha: captchaCode,
})
diff --git a/src/app/admin/(dashboard)/page.tsx b/src/app/admin/(dashboard)/page.tsx
index 692255d..e8f31ec 100644
--- a/src/app/admin/(dashboard)/page.tsx
+++ b/src/app/admin/(dashboard)/page.tsx
@@ -3,8 +3,6 @@ import Image from 'next/image'
import banner from './_assets/banner.webp'
import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card'
import {Button} from '@/components/ui/button'
-import {getProfile} from '@/actions/auth/auth'
-import {redirect} from 'next/navigation'
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs'
export type DashboardPageProps = {}
@@ -65,7 +63,7 @@ export default async function DashboardPage(props: DashboardPageProps) {
{/* 图表 */}
-
+
动态 IP 套餐
diff --git a/src/app/admin/_client/navbar.tsx b/src/app/admin/_client/navbar.tsx
index a30ebe1..b349e99 100644
--- a/src/app/admin/_client/navbar.tsx
+++ b/src/app/admin/_client/navbar.tsx
@@ -17,7 +17,7 @@ export default function Navbar(props: NavbarProps) {
)
@@ -75,10 +76,10 @@ function NavTitle(props: {
`transition-[opacity] duration-150 ease-in-out absolute mx-4`,
`group-data-[expand=true]:delay-[50ms] group-data-[expand=true]:opacity-100 group-data-[expand=false]:opacity-0`,
)}>{props.label}
-
+ )}>
)
}
@@ -87,7 +88,6 @@ function NavItem(props: {
href: string
icon?: ReactNode
label: string
- expand: boolean
}) {
return (
{
+ return {
+ title: 'Create Next App',
+ description: 'Generated by create next app',
+ }
}
export default async function RootLayout({
@@ -21,7 +24,8 @@ export default async function RootLayout({
children: ReactNode
}>) {
- const user = await getProfile()
+ const result = await getProfile()
+ const user = result.success ? result.data : null
return (
diff --git a/src/app/test/route.ts b/src/app/test/route.ts
new file mode 100644
index 0000000..e3a6836
--- /dev/null
+++ b/src/app/test/route.ts
@@ -0,0 +1,14 @@
+import {NextRequest, NextResponse} from 'next/server'
+
+export async function GET(req: NextRequest) {
+ const headers: {
+ [key: string]: string
+ } = {}
+ req.headers.forEach((value, key) => {
+ headers[key] = value
+ })
+ return NextResponse.json({
+ headers: headers,
+ cookies: req.cookies.getAll(),
+ })
+}
diff --git a/src/assets/logo-avatar.svg b/src/assets/logo-avatar.svg
new file mode 100644
index 0000000..d3873bd
--- /dev/null
+++ b/src/assets/logo-avatar.svg
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/components/providers/StoreProvider.tsx b/src/components/providers/StoreProvider.tsx
index d7d1ec1..cc01367 100644
--- a/src/components/providers/StoreProvider.tsx
+++ b/src/components/providers/StoreProvider.tsx
@@ -23,13 +23,13 @@ export default function StoreProvider(props: ProfileProviderProps) {
const profile = useRef>(null)
if (!profile.current) {
- console.log('create profile store')
+ console.log('📦 create profile store')
profile.current = createProfileStore(props.user)
}
const layout = useRef>(null)
if (!layout.current) {
- console.log('create layout store')
+ console.log('📦 create layout store')
layout.current = createLayoutStore()
}
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 3df7ee3..db53f0f 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,5 +1,3 @@
-// API工具函数
-
// 定义后端服务URL和OAuth2配置
const API_BASE_URL = process.env.API_BASE_URL
const CLIENT_ID = process.env.CLIENT_ID
diff --git a/src/middleware.ts b/src/middleware.ts
new file mode 100644
index 0000000..9129997
--- /dev/null
+++ b/src/middleware.ts
@@ -0,0 +1,38 @@
+import {NextRequest, NextResponse} from 'next/server'
+import {refreshAuth} from '@/actions/auth'
+
+export const config = {
+ matcher: [
+ '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*(? item.test(request.nextUrl.pathname))
+
+ if (match) {
+ try {
+ const accessToken = request.cookies.get('auth_token')
+ const refreshToken = request.cookies.get('auth_refresh')
+ if (!accessToken && refreshToken) {
+ console.log('💡 refresh token')
+ const token = await refreshAuth()
+ request.cookies.set('auth_token', token.access_token)
+ request.cookies.set('auth_refresh', token.refresh_token)
+ }
+ }
+ catch (error) {
+ return NextResponse.redirect(`${request.nextUrl.origin}/login?redirect=${request.nextUrl.pathname}`)
+ }
+ }
+
+ return NextResponse.next({request})
+}
diff --git a/src/stores/profile.ts b/src/stores/profile.ts
index 2e5d033..8ca289c 100644
--- a/src/stores/profile.ts
+++ b/src/stores/profile.ts
@@ -1,6 +1,6 @@
import {User} from '@/lib/models'
import {createStore} from 'zustand/vanilla'
-import {getProfile} from '@/actions/auth/auth'
+import {getProfile} from '@/actions/auth'
export type ProfileStore = ProfileState & ProfileActions
@@ -18,7 +18,8 @@ export const createProfileStore = (init: User|null) => {
profile: init,
refreshProfile: async () => {
const profile = await getProfile()
- setState({profile})
+ if (!profile.success) return
+ setState({profile: profile.data})
},
}))
}