2025-12-29 14:09:13 +08:00
|
|
|
"use server"
|
|
|
|
|
import { cookies } from "next/headers"
|
|
|
|
|
import type { ApiResponse } from "@/lib/api"
|
2026-01-09 17:34:57 +08:00
|
|
|
import type { User } from "@/models/user"
|
|
|
|
|
import { callByDevice, callByUser } from "./base"
|
2025-12-29 14:09:13 +08:00
|
|
|
|
2025-12-29 14:37:03 +08:00
|
|
|
export type TokenResp = {
|
|
|
|
|
access_token: string
|
|
|
|
|
refresh_token: string
|
|
|
|
|
expires_in: number
|
|
|
|
|
token_type: string
|
|
|
|
|
scope?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function login(params: {
|
|
|
|
|
username: string
|
|
|
|
|
password: string
|
|
|
|
|
remember: boolean
|
2026-03-31 10:56:01 +08:00
|
|
|
}): Promise<ApiResponse<string[]>> {
|
2025-12-29 14:37:03 +08:00
|
|
|
const resp = await callByDevice<TokenResp>("/api/auth/token", {
|
2025-12-29 14:09:13 +08:00
|
|
|
grant_type: "password",
|
|
|
|
|
login_type: "password",
|
|
|
|
|
login_pool: "admin",
|
|
|
|
|
...params,
|
|
|
|
|
})
|
|
|
|
|
if (!resp.success) {
|
|
|
|
|
return resp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存到 cookies
|
|
|
|
|
const data = resp.data
|
|
|
|
|
const cookieStore = await cookies()
|
2026-01-09 17:34:57 +08:00
|
|
|
cookieStore.set("admin/auth_token", data.access_token, {
|
2025-12-29 14:09:13 +08:00
|
|
|
httpOnly: true,
|
|
|
|
|
sameSite: "strict",
|
|
|
|
|
maxAge: Math.max(data.expires_in, 0),
|
|
|
|
|
})
|
2026-01-09 17:34:57 +08:00
|
|
|
cookieStore.set("admin/auth_refresh", data.refresh_token, {
|
2025-12-29 14:09:13 +08:00
|
|
|
httpOnly: true,
|
|
|
|
|
sameSite: "strict",
|
|
|
|
|
maxAge: Number.MAX_SAFE_INTEGER,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
2026-03-31 10:56:01 +08:00
|
|
|
data: data.scope?.split(" ") || [],
|
2025-12-29 14:09:13 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 17:34:57 +08:00
|
|
|
export async function logout() {
|
|
|
|
|
const cookieStore = await cookies()
|
|
|
|
|
|
|
|
|
|
// 尝试删除后台会话
|
|
|
|
|
const access_token = cookieStore.get("admin/auth_token")?.value
|
|
|
|
|
const refresh_token = cookieStore.get("admin/auth_refresh")?.value
|
|
|
|
|
if (access_token && refresh_token) {
|
|
|
|
|
await callByUser("/api/auth/revoke", {
|
|
|
|
|
access_token,
|
|
|
|
|
refresh_token,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除 cookies
|
|
|
|
|
cookieStore.set("admin/auth_token", "", {
|
|
|
|
|
httpOnly: true,
|
|
|
|
|
sameSite: "strict",
|
|
|
|
|
maxAge: -1,
|
|
|
|
|
})
|
|
|
|
|
cookieStore.set("admin/auth_refresh", "", {
|
|
|
|
|
httpOnly: true,
|
|
|
|
|
sameSite: "strict",
|
|
|
|
|
maxAge: -1,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
data: undefined,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getProfile() {
|
|
|
|
|
return await callByUser<User>("/api/auth/introspect")
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-29 14:37:03 +08:00
|
|
|
export async function refreshAuth() {
|
|
|
|
|
const cookie = await cookies()
|
2025-12-29 14:09:13 +08:00
|
|
|
|
2026-01-09 17:34:57 +08:00
|
|
|
const userRefresh = cookie.get("admin/auth_refresh")?.value
|
|
|
|
|
console.log(userRefresh, "userRefresh")
|
|
|
|
|
|
2025-12-29 14:37:03 +08:00
|
|
|
if (!userRefresh) {
|
|
|
|
|
throw new Error("未授权访问")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 请求刷新访问令牌
|
|
|
|
|
const resp = await callByDevice<TokenResp>(`/api/auth/token`, {
|
|
|
|
|
grant_type: "refresh_token",
|
|
|
|
|
refresh_token: userRefresh,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 处理请求
|
|
|
|
|
if (!resp.success) {
|
|
|
|
|
if (resp.status === 401) {
|
2026-01-09 17:34:57 +08:00
|
|
|
cookie.delete("admin/auth_refresh")
|
2025-12-29 14:37:03 +08:00
|
|
|
}
|
|
|
|
|
throw new Error("未授权访问")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析响应
|
|
|
|
|
const data = resp.data
|
|
|
|
|
const nextAccessToken = data.access_token
|
|
|
|
|
const nextRefreshToken = data.refresh_token
|
|
|
|
|
const expiresIn = data.expires_in
|
|
|
|
|
|
|
|
|
|
// 保存令牌到 cookies
|
2026-01-09 17:34:57 +08:00
|
|
|
cookie.set("admin/auth_token", nextAccessToken, {
|
2025-12-29 14:37:03 +08:00
|
|
|
httpOnly: true,
|
|
|
|
|
sameSite: "strict",
|
|
|
|
|
maxAge: Math.max(expiresIn, 0),
|
|
|
|
|
})
|
2026-01-09 17:34:57 +08:00
|
|
|
cookie.set("admin/auth_refresh", nextRefreshToken, {
|
2025-12-29 14:37:03 +08:00
|
|
|
httpOnly: true,
|
|
|
|
|
sameSite: "strict",
|
|
|
|
|
maxAge: Number.MAX_SAFE_INTEGER,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 返回新的访问令牌
|
|
|
|
|
return {
|
|
|
|
|
access_token: nextAccessToken,
|
|
|
|
|
refresh_token: nextRefreshToken,
|
|
|
|
|
}
|
2025-12-29 14:09:13 +08:00
|
|
|
}
|