106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
|
|
'use server'
|
||
|
|
import {cookies} from 'next/headers'
|
||
|
|
import {ApiResponse} from '@/lib/api'
|
||
|
|
import {AuthContext} from '@/lib/auth'
|
||
|
|
import {User} from '@/lib/models'
|
||
|
|
import {callByDevice, callByUser, getUserToken} from '@/actions/base'
|
||
|
|
|
||
|
|
export interface LoginParams {
|
||
|
|
username: string
|
||
|
|
password: string
|
||
|
|
remember?: boolean
|
||
|
|
}
|
||
|
|
|
||
|
|
type LoginResp = {
|
||
|
|
access_token: string
|
||
|
|
refresh_token: string
|
||
|
|
expires: number
|
||
|
|
auth: AuthContext
|
||
|
|
profile: User
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function login(props: LoginParams): Promise<ApiResponse> {
|
||
|
|
// 尝试登录
|
||
|
|
const result = await callByDevice<LoginResp>('/api/auth/login/sms', {
|
||
|
|
username: props.username,
|
||
|
|
password: props.password,
|
||
|
|
remember: props.remember ?? false,
|
||
|
|
})
|
||
|
|
if (!result.success) {
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
const data = result.data
|
||
|
|
|
||
|
|
// 保存到 cookies
|
||
|
|
const current = Math.floor(Date.now() / 1000)
|
||
|
|
const future = data.expires - current
|
||
|
|
|
||
|
|
const cookieStore = await cookies()
|
||
|
|
cookieStore.set('auth_token', data.access_token, {
|
||
|
|
httpOnly: true,
|
||
|
|
sameSite: 'strict',
|
||
|
|
secure: process.env.NODE_ENV === 'production',
|
||
|
|
maxAge: Math.max(future, 0),
|
||
|
|
})
|
||
|
|
cookieStore.set('auth_refresh', data.refresh_token, {
|
||
|
|
httpOnly: true,
|
||
|
|
sameSite: 'strict',
|
||
|
|
secure: process.env.NODE_ENV === 'production',
|
||
|
|
maxAge: 7 * 24 * 3600,
|
||
|
|
})
|
||
|
|
cookieStore.set('auth_info', JSON.stringify(data.auth), {
|
||
|
|
httpOnly: true,
|
||
|
|
sameSite: 'strict',
|
||
|
|
secure: process.env.NODE_ENV === 'production',
|
||
|
|
maxAge: 7 * 24 * 3600,
|
||
|
|
})
|
||
|
|
cookieStore.set('auth_profile', JSON.stringify(data.profile), {
|
||
|
|
httpOnly: true,
|
||
|
|
sameSite: 'strict',
|
||
|
|
secure: process.env.NODE_ENV === 'production',
|
||
|
|
maxAge: 7 * 24 * 3600,
|
||
|
|
})
|
||
|
|
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: undefined,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function getProfile(refresh: boolean = false) {
|
||
|
|
const cookie = await cookies()
|
||
|
|
|
||
|
|
// 获取缓存的用户信息
|
||
|
|
if (!refresh) {
|
||
|
|
const profile = cookie.get('auth_profile')?.value
|
||
|
|
if (profile) {
|
||
|
|
return JSON.parse(profile) as User
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取缓存的 token
|
||
|
|
let token: string
|
||
|
|
try {
|
||
|
|
token = await getUserToken()
|
||
|
|
}
|
||
|
|
catch (e) {
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
|
||
|
|
// 如果没有缓存,则请求用户信息
|
||
|
|
const result = await callByUser<User>('/api/user/get/token', {token})
|
||
|
|
if (!result.success) {
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
|
||
|
|
// 保存用户信息到cookie
|
||
|
|
cookie.set('auth_profile', JSON.stringify(result.data), {
|
||
|
|
httpOnly: true,
|
||
|
|
sameSite: 'strict',
|
||
|
|
secure: process.env.NODE_ENV === 'production',
|
||
|
|
maxAge: 7 * 24 * 3600,
|
||
|
|
})
|
||
|
|
|
||
|
|
return result.data
|
||
|
|
}
|