feat: Docker部署与CI/CD集成, 搜索栏修复, 上传目录改为data
This commit is contained in:
48
pages/api/v1/auth/login.ts
Normal file
48
pages/api/v1/auth/login.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { UserService } from '../../../../backend/services/userService';
|
||||
import { generateToken } from '../../../../lib/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ success: false, error: 'Method not allowed' });
|
||||
}
|
||||
|
||||
try {
|
||||
const { username, password } = req.body;
|
||||
|
||||
// Validate input
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({ success: false, error: 'Username and password are required' });
|
||||
}
|
||||
|
||||
// Authenticate user
|
||||
const user = await UserService.authenticateUser(username, password);
|
||||
|
||||
if (!user) {
|
||||
return res.status(401).json({ success: false, error: 'Invalid username or password' });
|
||||
}
|
||||
|
||||
// Check if user is banned
|
||||
if (user.status === 'BANNED') {
|
||||
return res.status(403).json({ success: false, error: 'Account has been banned' });
|
||||
}
|
||||
|
||||
// Generate JWT token
|
||||
const token = generateToken(user.id);
|
||||
|
||||
// Set HTTP-only cookie
|
||||
res.setHeader('Set-Cookie', `token=${token}; HttpOnly; Path=/; Max-Age=${7 * 24 * 60 * 60}; SameSite=Strict`);
|
||||
|
||||
// Return user data
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
data: {
|
||||
user,
|
||||
token // Also return token in body for non-cookie clients
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
return res.status(500).json({ success: false, error: 'Login failed' });
|
||||
}
|
||||
}
|
||||
15
pages/api/v1/auth/logout.ts
Normal file
15
pages/api/v1/auth/logout.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ success: false, error: 'Method not allowed' });
|
||||
}
|
||||
|
||||
// Clear the authentication cookie
|
||||
res.setHeader('Set-Cookie', 'token=; HttpOnly; Path=/; Max-Age=0; SameSite=Strict');
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
message: 'Logged out successfully'
|
||||
});
|
||||
}
|
||||
20
pages/api/v1/auth/me.ts
Normal file
20
pages/api/v1/auth/me.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { NextApiResponse } from 'next';
|
||||
import { AuthenticatedRequest, requireAuth } from '../../../../lib/middleware/authMiddleware';
|
||||
|
||||
export default async function handler(req: AuthenticatedRequest, res: NextApiResponse) {
|
||||
if (req.method !== 'GET') {
|
||||
return res.status(405).json({ success: false, error: 'Method not allowed' });
|
||||
}
|
||||
|
||||
// Require authentication
|
||||
const isAuthenticated = await requireAuth(req, res);
|
||||
if (!isAuthenticated) {
|
||||
return; // requireAuth already sent the response
|
||||
}
|
||||
|
||||
// Return current user data
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
data: req.user
|
||||
});
|
||||
}
|
||||
59
pages/api/v1/auth/register.ts
Normal file
59
pages/api/v1/auth/register.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { UserService } from '../../../../backend/services/userService';
|
||||
import { generateToken } from '../../../../lib/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ success: false, error: 'Method not allowed' });
|
||||
}
|
||||
|
||||
try {
|
||||
const { username, password, email } = req.body;
|
||||
|
||||
// Validate input
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({ success: false, error: 'Username and password are required' });
|
||||
}
|
||||
|
||||
if (username.length < 3) {
|
||||
return res.status(400).json({ success: false, error: 'Username must be at least 3 characters' });
|
||||
}
|
||||
|
||||
if (password.length < 6) {
|
||||
return res.status(400).json({ success: false, error: 'Password must be at least 6 characters' });
|
||||
}
|
||||
|
||||
// Check if username already exists
|
||||
const existingUser = await UserService.getUserByUsername(username);
|
||||
if (existingUser) {
|
||||
return res.status(409).json({ success: false, error: 'Username already taken' });
|
||||
}
|
||||
|
||||
// Create new user
|
||||
const user = await UserService.createUser(username, password, email);
|
||||
|
||||
// Generate JWT token
|
||||
const token = generateToken(user.id);
|
||||
|
||||
// Set HTTP-only cookie
|
||||
res.setHeader('Set-Cookie', `token=${token}; HttpOnly; Path=/; Max-Age=${7 * 24 * 60 * 60}; SameSite=Strict`);
|
||||
|
||||
// Return user data (without password)
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
data: {
|
||||
user: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
avatarUrl: user.avatarUrl,
|
||||
role: user.role,
|
||||
status: user.status
|
||||
},
|
||||
token // Also return token in body for non-cookie clients
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
return res.status(500).json({ success: false, error: 'Registration failed' });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user