unify note create/edit logic to fix various logic bugs and validation gaps

This commit is contained in:
Hazelnoot 2025-09-18 14:16:58 -04:00
parent 24bc1c653d
commit edb74066da
5 changed files with 93 additions and 144 deletions

View file

@ -302,7 +302,7 @@ export class NoteCreateService implements OnApplicationShutdown {
case 'followers':
// 他人のfollowers noteはreject
if (data.renote.userId !== user.id) {
throw new IdentifiableError('b6352a84-e5cd-4b05-a26c-63437a6b98ba', 'Renote target is not public or home');
throw new IdentifiableError('be9529e9-fe72-4de0-ae43-0b363c4938af', 'Renote target is not public or home');
}
// Renote対象がfollowersならfollowersにする
@ -310,25 +310,53 @@ export class NoteCreateService implements OnApplicationShutdown {
break;
case 'specified':
// specified / direct noteはreject
throw new IdentifiableError('b6352a84-e5cd-4b05-a26c-63437a6b98ba', 'Renote target is not public or home');
throw new IdentifiableError('be9529e9-fe72-4de0-ae43-0b363c4938af', 'Renote target is not public or home');
}
if (data.renote.userId !== user.id) {
// Check local-only
if (data.renote.localOnly && user.host != null) {
throw new IdentifiableError('12e23cec-edd9-442b-aa48-9c21f0c3b215', 'Remote user cannot renote a local-only note');
}
// Check visibility
if (!await this.noteEntityService.isVisibleForMe(data.renote, user.id)) {
throw new IdentifiableError('be9529e9-fe72-4de0-ae43-0b363c4938af', 'Cannot renote an invisible note');
}
// Check blocking
if (await this.userBlockingService.checkBlocked(data.renote.userId, user.id)) {
throw new IdentifiableError('b6352a84-e5cd-4b05-a26c-63437a6b98ba', 'Renote target is blocked');
}
}
}
if (data.reply) {
if (isPureRenote(data.reply)) {
throw new IdentifiableError('3ac74a84-8fd5-4bb0-870f-01804f82ce15', 'Cannot reply to a pure renote (boost)');
}
if (data.reply.userId !== user.id) {
// Check local-only
if (data.reply.localOnly && user.host != null) {
throw new IdentifiableError('12e23cec-edd9-442b-aa48-9c21f0c3b215', 'Remote user cannot reply to a local-only note');
}
// Check visibility
if (!await this.noteEntityService.isVisibleForMe(data.reply, user.id)) {
throw new IdentifiableError('b98980fa-3780-406c-a935-b6d0eeee10d1', 'Cannot reply to an invisible note');
}
// Check blocking
if (await this.userBlockingService.checkBlocked(data.reply.userId, user.id)) {
throw new IdentifiableError('b6352a84-e5cd-4b05-a26c-63437a6b98ba', 'Reply target is blocked');
}
}
}
// Check quote permissions
await this.checkQuotePermissions(data, user);
// Check blocking
if (this.isRenote(data) && !this.isQuote(data)) {
if (data.renote.userHost === null) {
if (data.renote.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id);
if (blocked) {
throw new IdentifiableError('b6352a84-e5cd-4b05-a26c-63437a6b98ba', 'Renote target is blocked');
}
}
}
}
// 返信対象がpublicではないならhomeにする
if (data.reply && data.reply.visibility !== 'public' && data.visibility === 'public') {
data.visibility = 'home';
@ -486,14 +514,6 @@ export class NoteCreateService implements OnApplicationShutdown {
mandatoryCW: data.mandatoryCW,
});
// should really not happen, but better safe than sorry
if (data.reply?.id === insert.id) {
throw new IdentifiableError('ea93b7c2-3d6c-4e10-946b-00d50b1a75cb', 'A note can\'t reply to itself');
}
if (data.renote?.id === insert.id) {
throw new IdentifiableError('ea93b7c2-3d6c-4e10-946b-00d50b1a75cb', 'A note can\'t renote itself');
}
if (data.uri != null) insert.uri = data.uri;
if (data.url != null) insert.url = data.url;