diff --git a/src/actions/authorizing.ts b/src/actions/authorizing.ts index 02d66e7..22e1ca1 100644 --- a/src/actions/authorizing.ts +++ b/src/actions/authorizing.ts @@ -5,58 +5,141 @@ import { revalidatePath } from "next/cache"; import { createAuthorization } from "@/lib/dto/authorization"; import { getAuthorizeUrl } from "@/lib/oauth/authorize-url"; import { prisma } from "@/lib/prisma"; +import { getCurrentUser } from "@/lib/session"; + +// 检查平台级权限 +async function checkPlatformAuthorization(clientId: string, userId: string) { + // 检查应用是否被平台禁用 + const client = await prisma.client.findUnique({ + where: { id: clientId }, + select: { enabled: true }, + }); + + if (!client) { + return { allowed: false, error: "应用不存在" }; + } + + if (!client.enabled) { + return { allowed: false, error: "该应用已被平台管理员禁用" }; + } + + // 检查用户授权是否被平台禁用 + const existingAuth = await prisma.authorization.findUnique({ + where: { + userId_clientId: { userId, clientId }, + }, + select: { enabled: true }, + }); + + if (existingAuth && !existingAuth.enabled) { + return { allowed: false, error: "您的授权已被平台管理员禁用" }; + } + + return { allowed: true }; +} + +// 检查应用级权限 +async function checkApplicationAuthorization( + clientId: string, + username: string, +) { + const client = await prisma.client.findUnique({ + where: { id: clientId }, + select: { allowedUsers: true, name: true }, + }); + + if (!client) { + return { allowed: false, error: "应用不存在" }; + } + + const isAllowedByOwner = + client.allowedUsers.length === 0 || client.allowedUsers.includes(username); + + if (!isAllowedByOwner) { + return { allowed: false, error: "此应用不允许您登录,请联系应用所有者" }; + } + + return { allowed: true }; +} export async function handleAuthorizeAction( oauth: string, - userId: string, clientId: string, scope: string, ) { try { - // 检查客户端是否限制了允许的用户 - const client = await prisma.client.findUnique({ - where: { id: clientId }, - select: { allowedUsers: true, name: true, enabled: true }, + // 获取当前登录用户 + const currentUser = await getCurrentUser(); + if (!currentUser?.id) { + return { error: "请先登录" }; + } + + // 获取用户信息 + const user = await prisma.user.findUnique({ + where: { id: currentUser.id }, + select: { username: true }, }); - if (!client) { - return { error: "应用不存在" }; + if (!user) { + return { error: "用户不存在" }; } - if (!client.enabled) { - return { error: "该应用已被禁用" }; + // 检查平台级权限 + const platformAuth = await checkPlatformAuthorization( + clientId, + currentUser.id, + ); + if (!platformAuth.allowed) { + return { error: platformAuth.error }; } - // 如果设置了允许的用户列表,检查当前用户是否在列表中 - if (client.allowedUsers.length > 0) { - const user = await prisma.user.findUnique({ - where: { id: userId }, - select: { username: true }, + // 检查应用级权限 + const appAuth = await checkApplicationAuthorization( + clientId, + user.username, + ); + if (!appAuth.allowed) { + return { error: appAuth.error }; + } + + // 检查或创建授权记录 + const existingAuth = await prisma.authorization.findUnique({ + where: { + userId_clientId: { + userId: currentUser.id, + clientId, + }, + }, + }); + + if (existingAuth) { + // 更新最后使用时间 + await prisma.authorization.update({ + where: { + userId_clientId: { + userId: currentUser.id, + clientId, + }, + }, + data: { + lastUsedAt: new Date(), + }, + }); + } else { + // 创建新的授权记录 + await createAuthorization({ + userId: currentUser.id, + clientId, + scope, + enabled: true, + lastUsedAt: new Date(), }); - - if (!user) { - return { error: "用户不存在" }; - } - - if (!client.allowedUsers.includes(user.username)) { - return { - error: "您没有权限使用此应用", - }; - } } + // 处理重定向 const oauthParams = new URLSearchParams(atob(oauth)); const redirectUrl = getAuthorizeUrl(oauthParams); - // 保存授权 - await createAuthorization({ - userId, - clientId, - scope, - enabled: true, // 新授权默认启用 - lastUsedAt: new Date(), // 首次授权时间作为最后使用时间 - }); - // 刷新相关页面 revalidatePath("/dashboard"); revalidatePath(`/dashboard/clients/${clientId}`); diff --git a/src/components/auth/authorization-card.tsx b/src/components/auth/authorization-card.tsx index 1b2e84a..2271bed 100644 --- a/src/components/auth/authorization-card.tsx +++ b/src/components/auth/authorization-card.tsx @@ -60,7 +60,6 @@ export function AuthorizationCard({ setError(null); const result = await handleAuthorizeAction( oauthParams, - client.userId, client.id, permissions[0].id, );