Files
tonePage/apps/backend/src/blog/blog.controller.ts

142 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
BadRequestException,
Body,
Controller,
Get,
Param,
ParseUUIDPipe,
Post,
Query,
Req,
UseGuards,
} from '@nestjs/common';
import { BlogService } from './blog.service';
import { UserService } from 'src/user/user.service';
import { createBlogCommentDto } from './dto/create.blogcomment.dto';
import { Throttle, ThrottlerGuard } from '@nestjs/throttler';
import { BlogPermission } from './blog.permission.enum';
import { OptionalAuthGuard } from 'src/auth/guards/optional-auth.guard';
import { AuthUser, CurrentUser } from 'src/auth/decorator/current-user.decorator';
import { Request } from 'express';
@Controller('blog')
export class BlogController {
constructor(
private readonly blogService: BlogService,
private readonly userService: UserService,
) { }
@Get()
getBlogs() {
return this.blogService.list();
}
@Get(':id')
async getBlog(
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
@Query('p') password?: string,
) {
const blog = await this.blogService.findById(id);
if (!blog) throw new BadRequestException('文章不存在或无权限访问');
if (!blog.permissions.includes(BlogPermission.Public)) {
// 无公开权限,则进一步检查是否有密码保护
if (!blog.permissions.includes(BlogPermission.ByPassword)) {
throw new BadRequestException('文章不存在或无权限访问');
} else {
// 判断密码是否正确
if (
!password ||
this.blogService.hashPassword(password) !== blog.password_hash
) {
throw new BadRequestException('文章不存在或无权限访问');
}
}
}
const blogDataRes = await fetch(`${blog.contentUrl}`);
const blogContent = await blogDataRes.text();
await this.blogService.incrementViewCount(id);
return {
id: blog.id,
title: blog.title,
description: blog.description,
createdAt: blog.createdAt,
content: blogContent,
};
}
@Get(':id/comments')
async getBlogComments(
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
) {
const blog = await this.blogService.findById(id);
if (!blog) throw new BadRequestException('文章不存在');
/** @todo 对文章可读性进行更详细的判定 */
if (
!blog.permissions.includes(BlogPermission.Public) &&
!blog.permissions.includes(BlogPermission.ByPassword)
) {
throw new BadRequestException('文章不存在或未公开');
}
return await this.blogService.getComments(blog);
}
// 该接口允许匿名评论但仍需验证userId合法性
@UseGuards(ThrottlerGuard, OptionalAuthGuard)
@Throttle({ default: { limit: 20, ttl: 60000 } })
@Post(':id/comment')
async createBlogComment(
@Param('id', new ParseUUIDPipe({ version: '4' })) id: string,
@Body() commentData: createBlogCommentDto,
@Req() req: Request,
@CurrentUser() authUser: AuthUser,
) {
const { userId } = (authUser ?? {}) as { userId: string | undefined };
const blog = await this.blogService.findById(id);
if (!blog) throw new BadRequestException('文章不存在');
if (!blog.permissions.includes(BlogPermission.AllowComments)) {
throw new BadRequestException('作者关闭了该文章的评论功能');
}
const user = userId ? await this.userService.findOne({ userId }) : null;
const ip = `${req.headers['x-forwarded-for'] || req.ip}`;
// 获取IP归属地
let address = '未知';
if (!['::1'].includes(ip)) {
const addressRes = await (
await fetch(
`https://mesh.if.iqiyi.com/aid/ip/info?version=1.1.1&ip=${ip}`,
)
).json();
if (addressRes?.code == 0) {
const country: string = addressRes?.data?.countryCN || '未知';
const province: string = addressRes?.data?.provinceCN || '中国';
if (country !== '中国') {
// 非中国,显示国家
address = country;
} else {
// 中国,显示省份
address = province;
}
}
}
const comment = {
...commentData,
blog,
user,
ip,
address,
};
return await this.blogService.createComment(comment);
}
}