merge: Fix note create/edit validation to prevent quote loops and other invalid notes (resolves #1194) (!1230)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1230 Closes #1194 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
commit
02e80f6ea6
7 changed files with 158 additions and 175 deletions
|
|
@ -18,7 +18,6 @@ import { NoteCreateService } from '@/core/NoteCreateService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { isQuote, isRenote } from '@/misc/is-renote.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { NoteVisibilityService } from '@/core/NoteVisibilityService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
|
|
@ -262,7 +261,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
private noteEntityService: NoteEntityService,
|
||||
private noteCreateService: NoteCreateService,
|
||||
private readonly noteVisibilityService: NoteVisibilityService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
if (ps.text && ps.text.length > this.config.maxNoteLength) {
|
||||
|
|
@ -303,31 +301,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
if (renote == null) {
|
||||
throw new ApiError(meta.errors.noSuchRenoteTarget);
|
||||
} else if (isRenote(renote) && !isQuote(renote)) {
|
||||
throw new ApiError(meta.errors.cannotReRenote);
|
||||
} else if (!(await this.noteVisibilityService.checkNoteVisibilityAsync(renote, me)).accessible) {
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
}
|
||||
|
||||
// Check blocking
|
||||
if (renote.userId !== me.id) {
|
||||
const blockExist = await this.blockingsRepository.exists({
|
||||
where: {
|
||||
blockerId: renote.userId,
|
||||
blockeeId: me.id,
|
||||
},
|
||||
});
|
||||
if (blockExist) {
|
||||
throw new ApiError(meta.errors.youHaveBeenBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
if (renote.visibility === 'followers' && renote.userId !== me.id) {
|
||||
// 他人のfollowers noteはreject
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
} else if (renote.visibility === 'specified') {
|
||||
// specified / direct noteはreject
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
}
|
||||
|
||||
if (renote.channelId && renote.channelId !== ps.channelId) {
|
||||
|
|
@ -351,26 +324,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
if (reply == null) {
|
||||
throw new ApiError(meta.errors.noSuchReplyTarget);
|
||||
} else if (isRenote(reply) && !isQuote(reply)) {
|
||||
throw new ApiError(meta.errors.cannotReplyToPureRenote);
|
||||
} else if (!(await this.noteVisibilityService.checkNoteVisibilityAsync(reply, me)).accessible) {
|
||||
throw new ApiError(meta.errors.cannotReplyToInvisibleNote);
|
||||
} else if (reply.visibility === 'specified' && ps.visibility !== 'specified') {
|
||||
throw new ApiError(meta.errors.cannotReplyToSpecifiedVisibilityNoteWithExtendedVisibility);
|
||||
}
|
||||
|
||||
// Check blocking
|
||||
if (reply.userId !== me.id) {
|
||||
const blockExist = await this.blockingsRepository.exists({
|
||||
where: {
|
||||
blockerId: reply.userId,
|
||||
blockeeId: me.id,
|
||||
},
|
||||
});
|
||||
if (blockExist) {
|
||||
throw new ApiError(meta.errors.youHaveBeenBlocked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.poll) {
|
||||
|
|
@ -428,6 +384,16 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
throw new ApiError(meta.errors.containsTooManyMentions);
|
||||
} else if (e.id === '1c0ea108-d1e3-4e8e-aa3f-4d2487626153') {
|
||||
throw new ApiError(meta.errors.quoteDisabledForUser);
|
||||
} else if (e.id === 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a') {
|
||||
throw new ApiError(meta.errors.cannotReRenote);
|
||||
} else if (e.id === 'b6352a84-e5cd-4b05-a26c-63437a6b98ba') {
|
||||
throw new ApiError(meta.errors.youHaveBeenBlocked);
|
||||
} else if (e.id === 'be9529e9-fe72-4de0-ae43-0b363c4938af') {
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
} else if (e.id === '3ac74a84-8fd5-4bb0-870f-01804f82ce15') {
|
||||
throw new ApiError(meta.errors.cannotReplyToPureRenote);
|
||||
} else if (e.id === 'b98980fa-3780-406c-a935-b6d0eeee10d1') {
|
||||
throw new ApiError(meta.errors.cannotReplyToInvisibleNote);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import { NoteEditService } from '@/core/NoteEditService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { isQuote, isRenote } from '@/misc/is-renote.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { NoteVisibilityService } from '@/core/NoteVisibilityService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
|
|
@ -312,7 +311,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
private noteEntityService: NoteEntityService,
|
||||
private noteEditService: NoteEditService,
|
||||
private readonly noteVisibilityService: NoteVisibilityService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
if (ps.text && ps.text.length > this.config.maxNoteLength) {
|
||||
|
|
@ -347,44 +345,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
}
|
||||
|
||||
let renote: MiNote | null = null;
|
||||
|
||||
if (ps.renoteId === ps.editId) {
|
||||
throw new ApiError(meta.errors.cannotQuoteCurrentPost);
|
||||
}
|
||||
|
||||
if (ps.renoteId != null) {
|
||||
// Fetch renote to note
|
||||
renote = await this.notesRepository.findOneBy({ id: ps.renoteId });
|
||||
|
||||
if (renote == null) {
|
||||
throw new ApiError(meta.errors.noSuchRenoteTarget);
|
||||
} else if (isRenote(renote) && !isQuote(renote)) {
|
||||
throw new ApiError(meta.errors.cannotReRenote);
|
||||
}
|
||||
|
||||
if (renote.renoteId === ps.editId) {
|
||||
throw new ApiError(meta.errors.cannotQuoteaQuoteOfCurrentPost);
|
||||
}
|
||||
|
||||
// Check blocking
|
||||
if (renote.userId !== me.id) {
|
||||
const blockExist = await this.blockingsRepository.exists({
|
||||
where: {
|
||||
blockerId: renote.userId,
|
||||
blockeeId: me.id,
|
||||
},
|
||||
});
|
||||
if (blockExist) {
|
||||
throw new ApiError(meta.errors.youHaveBeenBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
if (renote.visibility === 'followers' && renote.userId !== me.id) {
|
||||
// 他人のfollowers noteはreject
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
} else if (renote.visibility === 'specified') {
|
||||
// specified / direct noteはreject
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
}
|
||||
|
||||
if (renote.channelId && renote.channelId !== ps.channelId) {
|
||||
|
|
@ -408,26 +374,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
if (reply == null) {
|
||||
throw new ApiError(meta.errors.noSuchReplyTarget);
|
||||
} else if (isRenote(reply) && !isQuote(reply)) {
|
||||
throw new ApiError(meta.errors.cannotReplyToPureRenote);
|
||||
} else if (!(await this.noteVisibilityService.checkNoteVisibilityAsync(reply, me)).accessible) {
|
||||
throw new ApiError(meta.errors.cannotReplyToInvisibleNote);
|
||||
} else if (reply.visibility === 'specified' && ps.visibility !== 'specified') {
|
||||
throw new ApiError(meta.errors.cannotReplyToSpecifiedVisibilityNoteWithExtendedVisibility);
|
||||
}
|
||||
|
||||
// Check blocking
|
||||
if (reply.userId !== me.id) {
|
||||
const blockExist = await this.blockingsRepository.exists({
|
||||
where: {
|
||||
blockerId: reply.userId,
|
||||
blockeeId: me.id,
|
||||
},
|
||||
});
|
||||
if (blockExist) {
|
||||
throw new ApiError(meta.errors.youHaveBeenBlocked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.poll) {
|
||||
|
|
@ -483,6 +432,20 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
throw new ApiError(meta.errors.containsTooManyMentions);
|
||||
} else if (e.id === '1c0ea108-d1e3-4e8e-aa3f-4d2487626153') {
|
||||
throw new ApiError(meta.errors.quoteDisabledForUser);
|
||||
} else if (e.id === '33510210-8452-094c-6227-4a6c05d99f02') {
|
||||
throw new ApiError(meta.errors.cannotQuoteCurrentPost);
|
||||
} else if (e.id === 'ea93b7c2-3d6c-4e10-946b-00d50b1a75cb') {
|
||||
throw new ApiError(meta.errors.cannotQuoteaQuoteOfCurrentPost);
|
||||
} else if (e.id === 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a') {
|
||||
throw new ApiError(meta.errors.cannotReRenote);
|
||||
} else if (e.id === 'b6352a84-e5cd-4b05-a26c-63437a6b98ba') {
|
||||
throw new ApiError(meta.errors.youHaveBeenBlocked);
|
||||
} else if (e.id === 'be9529e9-fe72-4de0-ae43-0b363c4938af') {
|
||||
throw new ApiError(meta.errors.cannotRenoteDueToVisibility);
|
||||
} else if (e.id === '3ac74a84-8fd5-4bb0-870f-01804f82ce15') {
|
||||
throw new ApiError(meta.errors.cannotReplyToPureRenote);
|
||||
} else if (e.id === 'b98980fa-3780-406c-a935-b6d0eeee10d1') {
|
||||
throw new ApiError(meta.errors.cannotReplyToInvisibleNote);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue