完成博客添加时的权限指定

This commit is contained in:
2025-06-22 23:26:12 +08:00
parent f3193226e7
commit 857d73d2ba
4 changed files with 83 additions and 4 deletions

View File

@@ -1,4 +1,5 @@
import {
BadRequestException,
Body,
Controller,
Delete,
@@ -12,7 +13,9 @@ import {
import { AuthGuard } from '@nestjs/passport';
import { CreateBlogDto } from 'src/admin/dto/admin-web/create-blog.dto';
import { Role } from 'src/auth/role.enum';
import { BlogPermission } from 'src/blog/Blog.Permission.enum';
import { BlogService } from 'src/blog/blog.service';
import { Blog } from 'src/blog/entity/Blog.entity';
import { Roles } from 'src/common/decorators/role.decorator';
import { RolesGuard } from 'src/common/guard/roles.guard';
@@ -20,7 +23,7 @@ import { RolesGuard } from 'src/common/guard/roles.guard';
@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles(Role.Admin)
export class AdminWebBlogController {
constructor(private readonly adminWebBlogService: BlogService) {}
constructor(private readonly adminWebBlogService: BlogService) { }
@Get()
async list() {

View File

@@ -1,4 +1,5 @@
import { IsString } from 'class-validator';
import { IsEnum, IsString } from 'class-validator';
import { BlogPermission } from 'src/blog/Blog.Permission.enum';
export class CreateBlogDto {
@IsString()
@@ -9,4 +10,10 @@ export class CreateBlogDto {
@IsString()
contentUrl: string;
@IsEnum(BlogPermission, { each: true, message: '请求类型错误' })
permissions: BlogPermission[];
@IsString()
password: string;// 允许空串
}

View File

@@ -3,6 +3,8 @@ import { InjectRepository } from '@nestjs/typeorm';
import { Blog } from './entity/Blog.entity';
import { Repository } from 'typeorm';
import { BlogComment } from './entity/BlogComment.entity';
import { BlogPermission } from './Blog.Permission.enum';
import { createHash } from 'crypto';
@Injectable()
export class BlogService {
@@ -11,7 +13,7 @@ export class BlogService {
private readonly blogRepository: Repository<Blog>,
@InjectRepository(BlogComment)
private readonly blogCommentRepository: Repository<BlogComment>,
) {}
) { }
async list() {
return this.blogRepository.find({
@@ -22,7 +24,14 @@ export class BlogService {
});
}
async create(blog: Partial<Blog>) {
async create(dto: Partial<Blog> & { password: string }) {
const { password, ...blog } = dto;
if (blog.permissions.includes(BlogPermission.ByPassword)) {
if (password) {
blog.password_hash = createHash('sha256').update(`${password}`).digest('hex');
}
}
const newBlog = this.blogRepository.create(blog);
return this.blogRepository.save(newBlog);
}

View File

@@ -1,6 +1,7 @@
'use client'
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Dialog,
DialogContent,
@@ -12,6 +13,7 @@ import {
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { AdminApi } from "@/lib/api";
import { BlogPermission } from "@/lib/types/Blog.Permission.enum";
import { useState } from "react";
import { toast } from "sonner";
@@ -20,12 +22,29 @@ interface AddBlogProps {
onRefresh: () => void;
}
const blogPermissions = [
{
permission: BlogPermission.Public,
localText: '公开可读',
},
{
permission: BlogPermission.ByPassword,
localText: '受密码保护',
},
{
permission: BlogPermission.List,
localText: '显示在列表中',
},
] as const;
export default function AddBlog({ children, onRefresh }: AddBlogProps) {
const [open, setOpen] = useState(false);
const [blog, setBlog] = useState({
title: "",
description: "",
contentUrl: "",
permissions: [] as BlogPermission[],
password: "",
});
const handleSubmit = async () => {
@@ -41,6 +60,8 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
title: '',
description: '',
contentUrl: '',
permissions: [],
password: '',
})
} else {
throw new Error();
@@ -93,6 +114,45 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
onChange={(e) => setBlog({ ...blog, contentUrl: e.target.value })}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label className="text-right">
</Label>
<div className="col-span-3 flex gap-3 gap-x-8 flex-wrap">
{
blogPermissions.map((v, i) => (
<div key={`blog-permission-option-${i}`} className="flex gap-2">
<Checkbox
id={`blog-permission-option-checkbox-${i}`}
checked={blog.permissions.includes(v.permission)}
onCheckedChange={newChecked => {
setBlog({
...blog,
permissions: newChecked ?
[...blog.permissions, v.permission] :
[...blog.permissions].filter(p => p !== v.permission),
})
}} />
<Label htmlFor={`blog-permission-option-checkbox-${i}`} className="whitespace-nowrap">{v.localText}</Label>
</div>
))
}
</div>
</div>
{
blog.permissions.includes(BlogPermission.ByPassword) &&
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="password" className="text-right">
</Label>
<Input
id="password"
className="col-span-3"
value={blog.password}
onChange={(e) => setBlog({ ...blog, password: e.target.value })}
/>
</div>
}
</div>
<DialogFooter>
<Button type="button" variant='secondary' onClick={() => setOpen(false)}></Button>