Skip to content

Commit 00b66be

Browse files
authored
feat(core): 实现文章的发布/取消发布功能 (#2443)
* feat(migration): add isPublished field to posts and notes collections * feat(note, post): add publish status management for notes and posts * build(tsup): 添加 import.meta.url 支持 - 在 tsup 配置中添加 platform: 'node' 设置 - 注入 import.meta.url 兼容层,以支持不同模块格式 * build(core): 修改 mx-server 启动脚本路径 * feat(migration): 添加 v8.4.0 版本迁移脚本至history * feat(core): 修复未认证用户可查看未发布内容的安全问题 - 在 Note 和 Post 模块中添加了对未认证用户的访问限制 * fix(core): 回滚 mx-server 启动脚本路径 * feat(migration): 添加 v8.4.0 数据库脚本以更新 notes 集合字段 * feat(migration): 更新 v8.4.0 修复脚本以重命名 hide 字段并互换其值 * feat(note): 替换 hide 字段为 isPublished,更新相关查询和条件 * feat(note): 将 hide 字段替换为 isPublished,更新相关数据模型 * feat(migration): 添加 v8.4.0 fix2修复脚本以更新 posts 集合中的 isPublished 字段为true
1 parent 97cd8d4 commit 00b66be

26 files changed

+285
-67
lines changed

apps/core/ecosystem.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = {
99
apps: [
1010
{
1111
name: 'mx-server',
12-
script: 'index.js',
12+
script: './index.js',
1313
autorestart: true,
1414
exec_mode: 'cluster',
1515
watch: false,

apps/core/src/migration/history.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import v5_0_0__1 from './version/v5.0.0-1'
99
import v5_1_1 from './version/v5.1.1'
1010
import v5_6_0 from './version/v5.6.0'
1111
import v7_2_1 from './version/v7.2.1'
12+
import v8_4_0 from './version/v8.4.0'
13+
import v8_4_0__1 from './version/v8.4.0.fix1'
14+
import v8_4_0__2 from './version/v8.4.0.fix2'
1215

1316
export default [
1417
v200Alpha1,
@@ -22,4 +25,7 @@ export default [
2225
v5_1_1,
2326
v5_6_0,
2427
v7_2_1,
28+
v8_4_0,
29+
v8_4_0__1,
30+
v8_4_0__2,
2531
]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//patch for version 8.4.0 v1
2+
//移除Note中的isPublished字段,并将hide字段重命名为isPublished
3+
import type { Db } from 'mongodb'
4+
5+
export default (async function v0840Fix1(db: Db) {
6+
try {
7+
const notesCollection = db.collection('notes')
8+
9+
// 移除 isPublished 字段
10+
await notesCollection.updateMany(
11+
{},
12+
{ $unset: { isPublished: '' } },
13+
{ upsert: false },
14+
)
15+
16+
// 将 hide 字段重命名为 isPublished, 同时将true与false互换
17+
await notesCollection.updateMany(
18+
{},
19+
[
20+
{
21+
$set: {
22+
isPublished: {
23+
$cond: {
24+
if: { $eq: ['$hide', true] },
25+
then: false,
26+
else: true,
27+
},
28+
},
29+
},
30+
},
31+
{ $unset: 'hide' },
32+
],
33+
{ upsert: false },
34+
)
35+
} catch (error) {
36+
console.error('Migration v8.4.0 Fix1 failed:', error)
37+
throw error
38+
}
39+
})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// patch for version 8.4.0 v2
2+
// 将Posts中的isPublished字段全部设置为true
3+
import type { Db } from 'mongodb'
4+
5+
export default (async function v0840Fix2(db: Db) {
6+
try {
7+
const postsCollection = db.collection('posts')
8+
9+
// 将 isPublished 字段全部设置为 true
10+
await postsCollection.updateMany(
11+
{},
12+
{ $set: { isPublished: true } },
13+
{ upsert: false },
14+
)
15+
} catch (error) {
16+
console.error('Migration v8.4.0 Fix2 failed:', error)
17+
throw error
18+
}
19+
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// patch for version lower than v8.4.0
2+
// 本次migration会向posts和notes表中添加一个isPublished字段,默认值为true
3+
import type { Db } from 'mongodb'
4+
5+
export default (async function v0840(db: Db) {
6+
try {
7+
const postsCollection = db.collection('posts')
8+
const notesCollection = db.collection('notes')
9+
10+
// 添加 isPublished 字段到 posts 集合
11+
await postsCollection.updateMany(
12+
{},
13+
{ $set: { isPublished: true } },
14+
{ upsert: false },
15+
)
16+
17+
// 添加 isPublished 字段到 notes 集合
18+
await notesCollection.updateMany(
19+
{},
20+
{ $set: { isPublished: true } },
21+
{ upsert: false },
22+
)
23+
} catch (error) {
24+
console.error('Migration to v8.4.0 failed:', error)
25+
}
26+
})

apps/core/src/modules/activity/activity.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
670670
this.databaseService.db
671671
.collection(NOTE_COLLECTION_NAME)
672672
.find({
673-
hide: false,
673+
isPublished: true,
674674
})
675675
.sort({
676676
created: -1,
@@ -722,19 +722,19 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
722722
mood: 1,
723723
bookmark: 1,
724724
password: 1,
725-
hide: 1,
725+
isPublished: 1,
726726
},
727727
)
728728
.lean(),
729729
])
730730
return {
731731
posts,
732732
notes: notes.map((note) => {
733-
if (note.password || note.hide) {
733+
if (note.password || !note.isPublished) {
734734
note.title = '未公开的日记'
735735
}
736736

737-
return omit(note, 'password', 'hide')
737+
return omit(note, 'password', 'isPublished')
738738
}),
739739
}
740740
}

apps/core/src/modules/aggregate/aggregate.service.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export class AggregateService {
102102
this.noteService.model,
103103
!isAuthenticated
104104
? {
105-
hide: false,
105+
isPublished: true,
106106
password: undefined,
107107
}
108108
: {},
@@ -111,7 +111,7 @@ export class AggregateService {
111111

112112
this.findTop(
113113
this.postService.model,
114-
!isAuthenticated ? { hide: false } : {},
114+
!isAuthenticated ? { isPublished: true } : {},
115115
size,
116116
)
117117
.populate('categoryId')
@@ -162,7 +162,7 @@ export class AggregateService {
162162
this.noteService.model
163163
.find(
164164
{
165-
hide: false,
165+
isPublished: true,
166166
...addYearCondition(year),
167167
},
168168
'_id nid title weather mood created modified bookmark',
@@ -209,7 +209,7 @@ export class AggregateService {
209209

210210
this.noteService.model
211211
.find({
212-
hide: false,
212+
isPublished: true,
213213

214214
$or: [
215215
{
@@ -258,7 +258,7 @@ export class AggregateService {
258258
])
259259

260260
return combineTasks
261-
.flat(1)
261+
.flat()
262262
.sort((a, b) => -(a.published_at.getTime() - b.published_at.getTime()))
263263
}
264264

@@ -291,7 +291,7 @@ export class AggregateService {
291291

292292
this.noteService.model
293293
.find({
294-
hide: false,
294+
isPublished: true,
295295
$and: [
296296
{
297297
$or: [

apps/core/src/modules/category/category.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class CategoryController {
4646
async getCategories(@Query() query: MultiCategoriesQueryDto) {
4747
const { ids, joint, type = CategoryType.Category } = query // categories is category's mongo id
4848
if (ids) {
49-
const ignoreKeys = '-text -summary -hide -images -commentsIndex'
49+
const ignoreKeys = '-text -summary -isPublished -images -commentsIndex'
5050
if (joint) {
5151
const map = new Object()
5252

apps/core/src/modules/mcp/mcp.service.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@ export class McpService {
9494
*/
9595
async getNotes(page = 1, size = 10) {
9696
const query = this.noteService.model
97-
.find({ hide: false })
97+
.find({ isPublished: true })
9898
.sort({ created: -1 })
9999
.skip((page - 1) * size)
100100
.limit(size)
101101

102102
const notes = await query.exec()
103-
const total = await this.noteService.model.countDocuments({ hide: false })
103+
const total = await this.noteService.model.countDocuments({
104+
isPublished: true,
105+
})
104106

105107
return {
106108
data: notes,

apps/core/src/modules/note/note.controller.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
NidType,
3030
NotePasswordQueryDto,
3131
NoteQueryDto,
32+
SetNotePublishStatusDto,
3233
} from './note.dto'
3334
import { NoteModel, PartialNoteModel } from './note.model'
3435
import { NoteService } from './note.service'
@@ -68,8 +69,10 @@ export class NoteController {
6869
}
6970

7071
@Get(':id')
71-
@Auth()
72-
async getOneNote(@Param() params: MongoIdDto) {
72+
async getOneNote(
73+
@Param() params: MongoIdDto,
74+
@IsAuthenticated() isAuthenticated: boolean,
75+
) {
7376
const { id } = params
7477

7578
const current = await this.noteService.model
@@ -82,6 +85,11 @@ export class NoteController {
8285
throw new CannotFindException()
8386
}
8487

88+
// 非认证用户只能查看已发布的手记
89+
if (!isAuthenticated && !current.isPublished) {
90+
throw new CannotFindException()
91+
}
92+
8593
return current
8694
}
8795

@@ -95,9 +103,9 @@ export class NoteController {
95103
const half = size >> 1
96104
const { id } = params
97105
const select = isAuthenticated
98-
? 'nid _id title created hide'
106+
? 'nid _id title created isPublished'
99107
: 'nid _id title created'
100-
const condition = isAuthenticated ? {} : { hide: false }
108+
const condition = isAuthenticated ? {} : { isPublished: true }
101109

102110
// 当前文档直接找,不用加条件,反正里面的东西是看不到的
103111
const currentDocument = await this.noteService.model
@@ -197,7 +205,7 @@ export class NoteController {
197205
) {
198206
const { nid } = params
199207
const { password, single: isSingle } = query
200-
const condition = isAuthenticated ? {} : { hide: false }
208+
const condition = isAuthenticated ? {} : { isPublished: true }
201209
const current: NoteModel | null = await this.noteService.model
202210
.findOne({
203211
nid,
@@ -278,8 +286,8 @@ export class NoteController {
278286
sortOrder,
279287
} = query
280288
const condition: FilterQuery<NoteModel> = isAuthenticated
281-
? { $or: [{ hide: false }, { hide: true }] }
282-
: { hide: false }
289+
? { $or: [{ isPublished: false }, { isPublished: true }] }
290+
: { isPublished: true }
283291

284292
return await this.noteService.getNotePaginationByTopicId(
285293
id,
@@ -292,4 +300,16 @@ export class NoteController {
292300
{ ...condition },
293301
)
294302
}
303+
304+
@Patch('/:id/publish')
305+
@Auth()
306+
async setPublishStatus(
307+
@Param() params: MongoIdDto,
308+
@Body() body: SetNotePublishStatusDto,
309+
) {
310+
await this.noteService.updateById(params.id, {
311+
isPublished: body.isPublished,
312+
})
313+
return { success: true }
314+
}
295315
}

0 commit comments

Comments
 (0)