Commit 496f7668 authored by 何 广一's avatar 何 广一
Browse files

prisma & auth api

parent 35afac8f
......@@ -39,3 +39,5 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
/src/generated/prisma
......@@ -3,25 +3,32 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"dev": "pnpm run redis & next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"redis": "start redis-server --port 6379"
},
"dependencies": {
"@prisma/client": "6.14.0",
"next": "15.4.6",
"rate-limiter-flexible": "^7.2.0",
"react": "19.1.0",
"react-dom": "19.1.0",
"next": "15.4.6"
"redis": "^5.8.2",
"zod": "^4.1.1"
},
"devDependencies": {
"typescript": "^5",
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@tailwindcss/postcss": "^4",
"tailwindcss": "^4",
"concurrently": "^9.2.0",
"eslint": "^9",
"eslint-config-next": "15.4.6",
"@eslint/eslintrc": "^3"
"prisma": "6.14.0",
"tailwindcss": "^4",
"typescript": "^5"
}
}
This diff is collapsed.
-- CreateTable
CREATE TABLE "User" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"password" TEXT NOT NULL,
"salt" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "Room" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"roomName" TEXT NOT NULL,
"creatorId" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Room_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "Message" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"content" TEXT NOT NULL,
"roomId" INTEGER NOT NULL,
"senderId" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Message_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "Room" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "Message_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "User_name_key" ON "User"("name");
-- CreateIndex
CREATE INDEX "Room_creatorId_idx" ON "Room"("creatorId");
-- CreateIndex
CREATE INDEX "Message_roomId_idx" ON "Message"("roomId");
-- CreateIndex
CREATE INDEX "Message_senderId_idx" ON "Message"("senderId");
/*
Warnings:
- You are about to drop the column `senderId` on the `Message` table. All the data in the column will be lost.
- You are about to drop the column `creatorId` on the `Room` table. All the data in the column will be lost.
- The primary key for the `User` table will be changed. If it partially fails, the table could be left without primary key constraint.
- You are about to drop the column `id` on the `User` table. All the data in the column will be lost.
- Added the required column `senderName` to the `Message` table without a default value. This is not possible if the table is not empty.
- Added the required column `creatorToken` to the `Room` table without a default value. This is not possible if the table is not empty.
- Added the required column `userToken` to the `User` table without a default value. This is not possible if the table is not empty.
*/
-- CreateTable
CREATE TABLE "AuthToken" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"token" TEXT NOT NULL,
"userName" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
"ua" TEXT,
"ip" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "AuthToken_userName_fkey" FOREIGN KEY ("userName") REFERENCES "User" ("name") ON DELETE CASCADE ON UPDATE CASCADE
);
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Message" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"content" TEXT NOT NULL,
"roomId" INTEGER NOT NULL,
"senderName" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Message_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "Room" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "Message_senderName_fkey" FOREIGN KEY ("senderName") REFERENCES "User" ("name") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Message" ("content", "createdAt", "id", "roomId") SELECT "content", "createdAt", "id", "roomId" FROM "Message";
DROP TABLE "Message";
ALTER TABLE "new_Message" RENAME TO "Message";
CREATE INDEX "Message_roomId_idx" ON "Message"("roomId");
CREATE INDEX "Message_senderName_idx" ON "Message"("senderName");
CREATE TABLE "new_Room" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"roomName" TEXT NOT NULL,
"creatorToken" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Room_creatorToken_fkey" FOREIGN KEY ("creatorToken") REFERENCES "User" ("userToken") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Room" ("createdAt", "id", "roomName", "updatedAt") SELECT "createdAt", "id", "roomName", "updatedAt" FROM "Room";
DROP TABLE "Room";
ALTER TABLE "new_Room" RENAME TO "Room";
CREATE INDEX "Room_creatorToken_idx" ON "Room"("creatorToken");
CREATE TABLE "new_User" (
"name" TEXT NOT NULL PRIMARY KEY,
"password" TEXT NOT NULL,
"salt" TEXT NOT NULL,
"userToken" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_User" ("createdAt", "name", "password", "salt", "updatedAt") SELECT "createdAt", "name", "password", "salt", "updatedAt" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_name_key" ON "User"("name");
CREATE UNIQUE INDEX "User_userToken_key" ON "User"("userToken");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
-- CreateIndex
CREATE UNIQUE INDEX "AuthToken_token_key" ON "AuthToken"("token");
-- CreateIndex
CREATE INDEX "AuthToken_userName_idx" ON "AuthToken"("userName");
-- CreateIndex
CREATE INDEX "AuthToken_token_idx" ON "AuthToken"("token");
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "sqlite"
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
output = "../src/generated/prisma"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
name String @id @unique
password String
salt String
userToken String @unique
createdRooms Room[] @relation("RoomCreator")
messages Message[]
authTokens AuthToken[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model AuthToken {
id Int @id @default(autoincrement())
token String @unique
userName String
user User @relation(fields: [userName], references: [name], onDelete: Cascade)
expiresAt DateTime // 过期时间
ua String?
ip String?
createdAt DateTime @default(now())
@@index([userName])
@@index([token])
}
model Room {
id Int @id @default(autoincrement())
roomName String
creatorToken String
creator User @relation("RoomCreator", fields: [creatorToken], references: [userToken], onDelete: Cascade)
messages Message[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([creatorToken])
}
model Message {
id Int @id @default(autoincrement())
content String
roomId Int
room Room @relation(fields: [roomId], references: [id], onDelete: Cascade)
senderName String
sender User @relation(fields: [senderName], references: [name], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([roomId])
@@index([senderName])
}
\ No newline at end of file
import { NextRequest, NextResponse } from 'next/server';
import * as Ty from '../../../interface'
import * as Db from '../../room-api';
import * as Auth from '../../login-interface';
/*
- url: /api/auth/autoLogin
- method: POST
- Read & Check Cookie
*/
export async function POST(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Auth.LoginResult | null>>> {
const cookieData = await Db.VerifyCookie(req.cookies)
if('code' in cookieData) return NextResponse.json(cookieData);
const Args: Auth.AutoLoginArgs = {
cookie: cookieData
};
const loginResult = await Db.AutoLogin(Args)
return NextResponse.json(loginResult)
}
\ No newline at end of file
import { NextRequest, NextResponse } from 'next/server';
import * as Ty from '../../../interface'
import * as Db from '../../room-api';
import * as Auth from '../../login-interface';
/*
- url: /api/auth/login
- method: POST
- Set Cookie
*/
export async function POST(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Auth.LoginResult | null>>> {
const result = Auth.authArgsSchema.safeParse(await req.json());
if (!result.success) {
return Db.MakeError('无效的请求参数', 114514, 400);
}
const Args: Auth.AuthArgs = result.data;
Args.userIP = req.headers.get('x-forwarded-for') || null;
const loginResult = await Db.Login(Args);
const res = NextResponse.json(loginResult);
if(loginResult.data)
{
res.cookies.set('userToken', loginResult.data.cookie.userToken, { path: '/' });
res.cookies.set('authToken', loginResult.data.cookie.authToken, { path: '/' });
}
return res;
}
\ No newline at end of file
import { NextRequest, NextResponse } from 'next/server';
import * as Ty from '../../../interface'
import * as Db from '../../room-api';
import * as Auth from '../../login-interface';
/*
- url: /api/auth/logout
- method: POST
- Read & Check Cookie
*/
export async function POST(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<null>>> {
const cookieData = await Db.VerifyCookie(req.cookies)
if('code' in cookieData)return NextResponse.json(cookieData);
const logoutResult = await Db.Logout(cookieData);
const res = NextResponse.json(logoutResult);
res.cookies.set('userToken', '', { maxAge: 0, path: '/' });
res.cookies.set('authToken', '', { maxAge: 0, path: '/' });
return res;
}
\ No newline at end of file
import { NextRequest, NextResponse } from 'next/server';
import * as Ty from '../../../interface'
import * as Db from '../../room-api';
import * as Auth from '../../login-interface';
/*
- url: /api/auth/register
- method: POST
*/
export async function POST(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Auth.RegisterResult | null>>> {
const result = Auth.authArgsSchema.safeParse(await req.json());
if (!result.success) {
return Db.MakeError('无效的请求参数', 114514, 400);
}
const Args: Auth.AuthArgs = result.data;
Args.userIP = req.headers.get('x-forwarded-for') || null;
const registerResult = await Db.Register(Args);
return NextResponse.json(registerResult);
}
\ No newline at end of file
import { NextRequest, NextResponse } from 'next/server';
import * as Ty from '../../../interface'
import * as Db from '../../room-api';
import * as Auth from '../../login-interface';
/*
- url: /api/auth/startSession
- method: GET
*/
export async function GET(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Auth.Session | null>>> {
const result = await Db.StartAuthSession();
return NextResponse.json(result);
}
\ No newline at end of file
import {z} from 'zod';
export interface Session {
sessionId: string;
}
export interface AuthArgs {
sessionId: string;
username: string;
password: string;
userAgent: string | null;
userIP: string | null;
}
export interface LoginCookieData {
userToken: string;
authToken: string;
}
export interface LoginResult {
user: string;
cookie: LoginCookieData;
}
export interface RegisterResult {
user: string;
}
export interface AutoLoginArgs {
cookie: LoginCookieData;
}
export const cookieSchema = z.object({
userToken: z.string().nullable(),
authToken: z.string().nullable()
});
export const minPasswordLength = 8;
export const maxPasswordLength = 100;
export const authArgsSchema = z.object({
sessionId: z.string(),
username: z.string().min(2).max(100),
password: z.string().min(minPasswordLength).max(maxPasswordLength),
userAgent: z.string().max(200).nullable(),
userIP: z.string().max(100).nullable()
});
export const reloginErrorCode = 1919810;
export const invalidUserErrorCode = 8848;
export const notAuthorizedToDeleteRoomErrorCode = 2;
......@@ -14,6 +14,10 @@ interface MessageAddArgs {
- response: null (只要code为0即为成功)
*/
export async function POST(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<null>>> {
const cookieData = await Db.VerifyCookie(req.cookies);
if('code' in cookieData)return NextResponse.json(cookieData);
const { roomId, content, sender } = await req.json() as Ty.MessageAddArgs;
const response = await Db.AddMessage({ roomId, content, sender });
return NextResponse.json(response);
......
import { NextRequest, NextResponse } from 'next/server';
import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
import { createHash, randomBytes } from 'crypto';
import * as Ty from '../interface'
import {RoomInfo, State} from './tmp-state'
import {prisma, redis} from "@/lib/db";
import * as Auth from './login-interface';
export async function MakeError(message: string, code: number = 1): Promise<NextResponse<Ty.BackendResponse<null>>> {
export async function MakeError(message: string, code: number = 1, status: number = 500): Promise<NextResponse<Ty.BackendResponse<null>>> {
return NextResponse.json({
code,
message,
data: null
});
}, { status });
}
export async function GetRoomList(): Promise<Ty.BackendResponse<Ty.RoomListRes>> {
console.log('获取到的房间列表:', State.fakeRooms as Ty.RoomPreviewInfo[]);
const UserExists = async (name: string): Promise<boolean> => {
const user = await prisma.user.findUnique({
where: { name },
select: { name: true }
});
return user !== null;
};
const toFrontMsg = async (m: any) : Promise<Ty.Message | null> => {
if(!m.senderName.length) return null;
if(!await UserExists(m.senderName)) return null;
return {
messageId: m.id,
roomId: m.roomId,
sender: m.senderName,
content: m.content,
time: m.createdAt.getTime(),
};
};
const getUserToken = async (name: string) => {
const user = await prisma.user.findUnique({
where: { name },
select: { userToken: true }
});
return user ? user.userToken : null;
};
const getRandomToken = (): string => {
return [...crypto.getRandomValues(new Uint8Array(16))]
.map(b => b.toString(36))
.join('');
};
const getRandomStr = () => (randomBytes(32).toString('hex'));
export async function GetRoomList(): Promise<Ty.BackendResponse<Ty.RoomListRes | null>> {
const rooms = await prisma.room.findMany({
select: {
id: true,
roomName: true,
messages: {
orderBy: { createdAt: 'desc' },
take: 1
},
},
});
const preview: Ty.RoomPreviewInfo[] = await Promise.all(rooms.map(async (r) => {
const lastMessage = r.messages[0] ? await toFrontMsg(r.messages[0]) : null;
return {
roomId: r.id,
roomName: r.roomName,
lastMessage
};
}));
return {
code: 0,
message: '房间获取成功',
data: {
rooms: State.fakeRooms as Ty.RoomPreviewInfo[]
rooms: preview
}
};
}
export async function AddRoom(data: Ty.RoomAddArgs): Promise<Ty.BackendResponse<Ty.RoomAddResult>> {
const newRoom: RoomInfo = {
roomId: State.maxRoomId + 1,
roomName: data.roomName,
lastMessage: null,
creator: data.user
const userName = data.user;
const creatorToken = await getUserToken(userName);
if(!creatorToken)
{
return {
code: 1,
message: '用户不存在',
data: {
roomId: -1
}
};
State.fakeRooms = [...State.fakeRooms, newRoom];
console.log('当前房间列表:', State.fakeRooms);
State.maxRoomId++;
}
const newRoom = await prisma.room.create({
data: {
roomName: data.roomName,
creatorToken
}
});
return {
code: 0,
message: '房间创建成功',
data: {
roomId: newRoom.roomId
roomId: newRoom.id
}
};
}
export async function GetMessageList(data : Ty.RoomMessageListArgs): Promise<Ty.BackendResponse<Ty.RoomMessageListRes>> {
const { roomId } = data;
const messages = State.fakeMsg.filter(msg => msg.roomId === roomId);
const messages = await prisma.message.findMany({
where: { roomId },
orderBy: { createdAt: 'asc' }
});
const messageList: Ty.Message[] =
await Promise.all(messages.map(toFrontMsg))
.then(msgs => msgs.filter((m): m is Ty.Message => m !== null));
return {
code: 0,
message: '消息获取成功',
data: {
messages
messages: messageList
}
};
}
export async function UpdateMessageList(data: Ty.RoomMessageGetUpdateArgs): Promise<Ty.BackendResponse<Ty.RoomMessageGetUpdateRes>> {
const { roomId, sinceMessageId } = data;
const messages = State.fakeMsg.filter(msg => msg.roomId === roomId && msg.messageId > sinceMessageId);
const messages = await prisma.message.findMany({
where: {
roomId,
id: { gt: sinceMessageId }
},
orderBy: { createdAt: 'asc' }
});
const messageList: Ty.Message[] =
await Promise.all(messages.map(toFrontMsg))
.then(msgs => msgs.filter((m): m is Ty.Message => m !== null));
return {
code: 0,
message: '消息更新成功',
data: {
messages
messages: messageList
}
};
}
//后续需要补上房间建立者和删除者不同的无权限错误
export async function DeleteRoom(data: Ty.RoomDeleteArgs): Promise<Ty.BackendResponse<null>> {
export async function DeleteRoom(data: Ty.RoomDeleteArgs, operatorToken: String ): Promise<Ty.BackendResponse<null>> {
const { user, roomId } = data;
State.fakeRooms = State.fakeRooms.filter(room => room.roomId !== roomId);
State.fakeMsg = State.fakeMsg.filter(msg => msg.roomId !== roomId);
const room = await prisma.room.findUnique({
where: { id: roomId },
select: { creator: { select: { name: true, userToken: true } } }
});
if (!room || room.creator.name !== user || room.creator.userToken !== operatorToken) {
return {
code: Auth.notAuthorizedToDeleteRoomErrorCode,
message: '无权限',
data: null
};
}
await prisma.room.delete({
where: { id: roomId }
});
return {
code: 0,
message: '房间删除成功',
......@@ -78,18 +185,235 @@ export async function DeleteRoom(data: Ty.RoomDeleteArgs): Promise<Ty.BackendRes
export async function AddMessage(data: Ty.MessageAddArgs): Promise<Ty.BackendResponse<null>> {
const { roomId, sender, content } = data;
const newMessage: Ty.Message = {
messageId: State.maxMessageId + 1,
roomId,
sender,
content,
time: Date.now()
console.log(`Adding message to room ${roomId} from user ${sender}: ${content}`);
if (!await UserExists(sender)) {
return {
code: 1,
message: '用户不存在',
data: null
};
State.fakeMsg = [...State.fakeMsg, newMessage];
State.maxMessageId++;
}
await prisma.message.create({
data: {
roomId,
senderName: sender,
content
}
});
return {
code: 0,
message: '消息发送成功',
data: null
};
}
export async function StartAuthSession() : Promise<Ty.BackendResponse<Auth.Session>> {
const sessionId = getRandomToken();
redis.set(`Session:${sessionId}`, "{}");
redis.expire(`Session:${sessionId}`, 60 * 5); // 5分钟内登录/注册有效
return {
code: 0,
message: '获取成功',
data: {
sessionId,
}
};
}
export async function Login(args: Auth.AuthArgs) : Promise<Ty.BackendResponse<Auth.LoginResult | null>> {
const { sessionId, username, password, userAgent, userIP } = args;
const sessionStr = await redis.get(`Session:${sessionId}`);
if(!sessionStr)
{
return {
code: 1,
message: '会话过期,请刷新页面后重试',
data: null
};
}
const user = await prisma.user.findUnique({
where: { name: username },
select: { password: true, salt: true, userToken: true }
});
if(!user || user.password !== createHash('sha256').update(password + user.salt).digest('hex'))
{
return {
code: 3,
message: '用户名或密码错误',
data: null
};
}
const authToken = getRandomToken();
await prisma.authToken.create({
data: {
token: authToken,
userName: username,
expiresAt: new Date(Date.now() + 60 * 60 * 1000 * 24 * 7), // 7 days
ua: userAgent,
ip: userIP
}
});
await redis.del(`Session:${sessionId}`);
return {
code: 0,
message: '登录成功',
data: {
user: username,
cookie: {
userToken: user.userToken,
authToken
}
}
};
}
export async function AutoLogin(args: Auth.AutoLoginArgs) : Promise<Ty.BackendResponse<Auth.LoginResult | null>> {
const { cookie } = args;
const { authToken } = cookie;
const user = await prisma.authToken.findUnique({
where: { token: authToken },
select: { user: true, expiresAt: true }
});
if (!user) {
return {
code: 101,
message: '无效的用户信息',
data: null
};
}
return {
code: 0,
message: '自动登录成功',
data: {
user: user.user.name,
cookie: {
userToken: cookie.userToken,
authToken: cookie.authToken
}
}
};
}
export async function Register(args: Auth.AuthArgs) : Promise<Ty.BackendResponse<Auth.RegisterResult | null>> {
const { sessionId, username, password } = args;
const sessionStr = await redis.get(`Session:${sessionId}`);
if(!sessionStr)
{
return {
code: 1,
message: '会话过期,请刷新页面后重试',
data: null
};
}
const user = await prisma.user.findUnique({
where: { name: username },
select: { name: true }
});
if(user)
{
return {
code: 3,
message: '用户名已存在',
data: null
};
}
const salt = getRandomStr();
const hashedPassword = createHash('sha256').update(password + salt).digest('hex');
await prisma.user.create({
data: {
name: username,
password: hashedPassword,
salt,
userToken: getRandomToken()
}
});
await redis.del(`Session:${sessionId}`);
return {
code: 0,
message: '注册成功',
data: {
user: username,
}
};
}
export async function Logout(args: Auth.LoginCookieData) : Promise<Ty.BackendResponse<null>> {
const { authToken } = args;
await prisma.authToken.delete({
where: { token: authToken }
});
return {
code: 0,
message: '登出成功',
data: null
};
}
export async function VerifyCookie(cookie : RequestCookies) : Promise<Ty.BackendResponse<null> | Auth.LoginCookieData> {
const result = Auth.cookieSchema.safeParse({
userToken: cookie.get('userToken')?.value || null,
authToken: cookie.get('authToken')?.value || null
});
if(!result.success || !result.data.authToken || !result.data.userToken) {
return {
code: 1,
message: '无效的Cookie',
data: null
};
}
const user = await prisma.authToken.findUnique({
where: { token: result.data.authToken },
select: { user: true, expiresAt: true }
});
if (!user || user.user.userToken !== result.data.userToken) {
return {
code: Auth.invalidUserErrorCode,
message: '无效的用户信息',
data: null
};
}
if (user.expiresAt < new Date()) {
await prisma.authToken.delete({
where: { token: result.data.authToken }
});
return {
code: Auth.reloginErrorCode,
message: '登录过期,请重新登录。',
data: null
};
}
const cookieData: Auth.LoginCookieData = {
userToken: result.data.userToken,
authToken: result.data.authToken
};
return cookieData;
}
\ No newline at end of file
......@@ -14,7 +14,11 @@ interface RoomDeleteArgs {
*/
export async function POST(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<null>>> {
const cookieData = await Db.VerifyCookie(req.cookies);
if('code' in cookieData) return NextResponse.json(cookieData);
const { user, roomId } = await req.json() as Ty.RoomDeleteArgs;
const response = await Db.DeleteRoom({ user, roomId });
const response = await Db.DeleteRoom({ user, roomId }, cookieData.userToken);
return NextResponse.json(response);
}
\ No newline at end of file
......@@ -11,8 +11,10 @@ interface RoomListRes {
rooms: RoomPreviewInfo[];
}
*/
export async function GET(req: NextRequest) :
Promise<NextResponse<Ty.BackendResponse<Ty.RoomListRes>>> {
export async function GET(req: NextRequest) : Promise<NextResponse<Ty.BackendResponse<Ty.RoomListRes | null>>> {
const cookieData = await Db.VerifyCookie(req.cookies);
if('code' in cookieData) return NextResponse.json(cookieData);
const response = await Db.GetRoomList();
return NextResponse.json(response);
}
\ No newline at end of file
......@@ -16,7 +16,11 @@ interface RoomMessageGetUpdateRes {
}
*/
export async function GET(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Ty.RoomMessageGetUpdateRes>>> {
export async function GET(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Ty.RoomMessageGetUpdateRes | null>>> {
const cookieData = await Db.VerifyCookie(req.cookies);
if('code' in cookieData) return NextResponse.json(cookieData);
const Params = req.nextUrl.searchParams;
const result = await Db.UpdateMessageList({
roomId: Number(Params.get('roomId')),
......
......@@ -14,7 +14,10 @@ interface RoomMessageListRes {
messages: Message[];
}
*/
export async function GET(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Ty.RoomMessageListRes>>> {
export async function GET(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Ty.RoomMessageListRes | null>>> {
const cookieData = await Db.VerifyCookie(req.cookies);
if('code' in cookieData) return NextResponse.json(cookieData);
const Params = req.nextUrl.searchParams;
const response = await Db.GetMessageList({ roomId: Number(Params.get('roomId')) });
return NextResponse.json(response);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment