diff --git a/src/models/note.ts b/src/models/note.ts index 8ca65bb42..a872eb769 100644 --- a/src/models/note.ts +++ b/src/models/note.ts @@ -140,6 +140,12 @@ export const hideNote = async (packedNote: any, meId: mongo.ObjectID) => { hide = true; } else if (meId.equals(packedNote.userId)) { hide = false; + } else if (packedNote.reply && meId.equals(packedNote.reply.userId)) { + // 自分の投稿に対するリプライ + hide = false; + } else if (packedNote.mentions && packedNote.mentions.some((id: any) => meId.equals(id))) { + // 自分へのメンション + hide = false; } else { // フォロワーかどうか const following = await Following.findOne({ diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index 874759060..e37d475df 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -53,14 +53,23 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => { const visibleQuery = [{ visibility: { $in: [ 'public', 'home' ] } }, { - // myself (for specified/private) + // myself (for followers/specified/private) userId: user._id }, { // to me (for specified) visibleUserIds: { $in: [ user._id ] } }, { visibility: 'followers', - userId: { $in: followings.map(f => f.id) } + $or: [{ + // フォロワーの投稿 + userId: { $in: followings.map(f => f.id) }, + }, { + // 自分の投稿へのリプライ + '_reply.userId': user._id, + }, { + // 自分へのメンションが含まれている + mentions: { $in: [ user._id ] } + }] }]; const query = { diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts index 112156403..199139c8e 100644 --- a/src/server/api/endpoints/notes/replies.ts +++ b/src/server/api/endpoints/notes/replies.ts @@ -51,14 +51,23 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => { }] : [{ visibility: { $in: [ 'public', 'home' ] } }, { - // myself (for specified/private) + // myself (for followers/specified/private) userId: user._id }, { // to me (for specified) visibleUserIds: { $in: [ user._id ] } }, { visibility: 'followers', - userId: { $in: followings.map(f => f.id) } + $or: [{ + // フォロワーの投稿 + userId: { $in: followings.map(f => f.id) }, + }, { + // 自分の投稿へのリプライ + '_reply.userId': user._id, + }, { + // 自分へのメンションが含まれている + mentions: { $in: [ user._id ] } + }] }]; const q = { diff --git a/test/api-visibility.ts b/test/api-visibility.ts index 56e72f7ca..8380d54f1 100644 --- a/test/api-visibility.ts +++ b/test/api-visibility.ts @@ -302,9 +302,9 @@ describe('API visibility', () => { expect(res.body).have.property('text').eql('x'); })); - it('[show] followers-replyを非フォロワーはリプライされていても見れない', async(async () => { + it('[show] followers-replyを非フォロワーでもリプライされていれば見れる', async(async () => { const res = await show(folR.id, target); - expect(res.body).have.property('isHidden').eql(true); + expect(res.body).have.property('text').eql('x'); })); it('[show] followers-replyをフォロワーが見れる', async(async () => { @@ -434,9 +434,9 @@ describe('API visibility', () => { expect(res.body).have.property('text').eql('@target x'); })); - it('[show] followers-mentionを非フォロワーはメンションされていても見れない', async(async () => { + it('[show] followers-mentionを非フォロワーでもメンションされていれば見れる', async(async () => { const res = await show(folM.id, target); - expect(res.body).have.property('isHidden').eql(true); + expect(res.body).have.property('text').eql('@target x'); })); it('[show] followers-mentionをフォロワーが見れる', async(async () => { @@ -531,62 +531,41 @@ describe('API visibility', () => { //#endregion //#region RTL - it('[RTL] followers-reply が 非フォロワー (リプライ先ではない) から見れない', async(async () => { + it('[replies] followers-reply が フォロワーから見れる', async(async () => { + const res = await request('/notes/replies', { noteId: tgt.id, limit: 100 }, follower); + expect(res).have.status(200); + const notes = res.body.filter((n: any) => n.id == folR.id); + expect(notes[0]).have.property('text').eql('x'); + })); + + it('[replies] followers-reply が 非フォロワー (リプライ先ではない) から見れない', async(async () => { const res = await request('/notes/replies', { noteId: tgt.id, limit: 100 }, other); expect(res).have.status(200); const notes = res.body.filter((n: any) => n.id == folR.id); expect(notes).length(0); })); - it('[RTL] followers-reply が 非フォロワー (リプライ先である) から見れない', async(async () => { + it('[replies] followers-reply が 非フォロワー (リプライ先である) から見れる', async(async () => { const res = await request('/notes/replies', { noteId: tgt.id, limit: 100 }, target); expect(res).have.status(200); const notes = res.body.filter((n: any) => n.id == folR.id); - expect(notes).length(0); + expect(notes[0]).have.property('text').eql('x'); })); //#endregion //#region MTL - it('[MTL] public-reply が 非フォロワー (リプライ先ではない) から見れる', async(async () => { - const res = await request('/notes/mentions', { noteId: tgt.id, limit: 100 }, other); - expect(res).have.status(200); - const notes = res.body.filter((n: any) => n.id == pubR.id); - expect(notes).length(0); - })); - - it('[MTL] followers-reply が 非フォロワー (リプライ先ではない) から見れない', async(async () => { - const res = await request('/notes/mentions', { noteId: tgt.id, limit: 100 }, other); + it('[mentions] followers-reply が 非フォロワー (リプライ先である) から見れる', async(async () => { + const res = await request('/notes/mentions', { limit: 100 }, target); expect(res).have.status(200); const notes = res.body.filter((n: any) => n.id == folR.id); - expect(notes).length(0); + expect(notes[0]).have.property('text').eql('x'); })); - it('[MTL] followers-reply が 非フォロワー (リプライ先である) から見れない', async(async () => { - const res = await request('/notes/mentions', { noteId: tgt.id, limit: 100 }, target); - expect(res).have.status(200); - const notes = res.body.filter((n: any) => n.id == folR.id); - expect(notes).length(0); - })); - - it('[MTL] public-mention が 非フォロワー (メンション先ではない) から見れる', async(async () => { - const res = await request('/notes/mentions', { noteId: tgt.id, limit: 100 }, other); - expect(res).have.status(200); - const notes = res.body.filter((n: any) => n.id == pubM.id); - expect(notes).length(0); - })); - - it('[MTL] followers-mention が 非フォロワー (メンション先ではない) から見れない', async(async () => { - const res = await request('/notes/mentions', { noteId: tgt.id, limit: 100 }, other); + it('[mentions] followers-mention が 非フォロワー (メンション先である) から見れる', async(async () => { + const res = await request('/notes/mentions', { limit: 100 }, target); expect(res).have.status(200); const notes = res.body.filter((n: any) => n.id == folM.id); - expect(notes).length(0); - })); - - it('[MTL] followers-reply が 非フォロワー (メンション先である) から見れない', async(async () => { - const res = await request('/notes/mentions', { noteId: tgt.id, limit: 100 }, target); - expect(res).have.status(200); - const notes = res.body.filter((n: any) => n.id == folM.id); - expect(notes).length(0); + expect(notes[0]).have.property('text').eql('@target x'); })); //#endregion });