完成博客添加时的权限指定
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
BadRequestException,
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
Delete,
|
Delete,
|
||||||
@@ -12,7 +13,9 @@ import {
|
|||||||
import { AuthGuard } from '@nestjs/passport';
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
import { CreateBlogDto } from 'src/admin/dto/admin-web/create-blog.dto';
|
import { CreateBlogDto } from 'src/admin/dto/admin-web/create-blog.dto';
|
||||||
import { Role } from 'src/auth/role.enum';
|
import { Role } from 'src/auth/role.enum';
|
||||||
|
import { BlogPermission } from 'src/blog/Blog.Permission.enum';
|
||||||
import { BlogService } from 'src/blog/blog.service';
|
import { BlogService } from 'src/blog/blog.service';
|
||||||
|
import { Blog } from 'src/blog/entity/Blog.entity';
|
||||||
import { Roles } from 'src/common/decorators/role.decorator';
|
import { Roles } from 'src/common/decorators/role.decorator';
|
||||||
import { RolesGuard } from 'src/common/guard/roles.guard';
|
import { RolesGuard } from 'src/common/guard/roles.guard';
|
||||||
|
|
||||||
@@ -20,7 +23,7 @@ import { RolesGuard } from 'src/common/guard/roles.guard';
|
|||||||
@UseGuards(AuthGuard('jwt'), RolesGuard)
|
@UseGuards(AuthGuard('jwt'), RolesGuard)
|
||||||
@Roles(Role.Admin)
|
@Roles(Role.Admin)
|
||||||
export class AdminWebBlogController {
|
export class AdminWebBlogController {
|
||||||
constructor(private readonly adminWebBlogService: BlogService) {}
|
constructor(private readonly adminWebBlogService: BlogService) { }
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async list() {
|
async list() {
|
||||||
|
|||||||
@@ -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 {
|
export class CreateBlogDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -9,4 +10,10 @@ export class CreateBlogDto {
|
|||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
contentUrl: string;
|
contentUrl: string;
|
||||||
|
|
||||||
|
@IsEnum(BlogPermission, { each: true, message: '请求类型错误' })
|
||||||
|
permissions: BlogPermission[];
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
password: string;// 允许空串
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import { Blog } from './entity/Blog.entity';
|
import { Blog } from './entity/Blog.entity';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { BlogComment } from './entity/BlogComment.entity';
|
import { BlogComment } from './entity/BlogComment.entity';
|
||||||
|
import { BlogPermission } from './Blog.Permission.enum';
|
||||||
|
import { createHash } from 'crypto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BlogService {
|
export class BlogService {
|
||||||
@@ -11,7 +13,7 @@ export class BlogService {
|
|||||||
private readonly blogRepository: Repository<Blog>,
|
private readonly blogRepository: Repository<Blog>,
|
||||||
@InjectRepository(BlogComment)
|
@InjectRepository(BlogComment)
|
||||||
private readonly blogCommentRepository: Repository<BlogComment>,
|
private readonly blogCommentRepository: Repository<BlogComment>,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
async list() {
|
async list() {
|
||||||
return this.blogRepository.find({
|
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);
|
const newBlog = this.blogRepository.create(blog);
|
||||||
return this.blogRepository.save(newBlog);
|
return this.blogRepository.save(newBlog);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -12,6 +13,7 @@ import {
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { AdminApi } from "@/lib/api";
|
import { AdminApi } from "@/lib/api";
|
||||||
|
import { BlogPermission } from "@/lib/types/Blog.Permission.enum";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
@@ -20,12 +22,29 @@ interface AddBlogProps {
|
|||||||
onRefresh: () => void;
|
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) {
|
export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [blog, setBlog] = useState({
|
const [blog, setBlog] = useState({
|
||||||
title: "",
|
title: "",
|
||||||
description: "",
|
description: "",
|
||||||
contentUrl: "",
|
contentUrl: "",
|
||||||
|
permissions: [] as BlogPermission[],
|
||||||
|
password: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
@@ -41,6 +60,8 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
|||||||
title: '',
|
title: '',
|
||||||
description: '',
|
description: '',
|
||||||
contentUrl: '',
|
contentUrl: '',
|
||||||
|
permissions: [],
|
||||||
|
password: '',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@@ -93,6 +114,45 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
|||||||
onChange={(e) => setBlog({ ...blog, contentUrl: e.target.value })}
|
onChange={(e) => setBlog({ ...blog, contentUrl: e.target.value })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button type="button" variant='secondary' onClick={() => setOpen(false)}>取消</Button>
|
<Button type="button" variant='secondary' onClick={() => setOpen(false)}>取消</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user