diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2025-05-11 06:02:52 -0400 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2025-05-11 06:02:52 -0400 |
| commit | d3a9995d0a252af877f401dc92802fb841291fa1 (patch) | |
| tree | 159dc485b80644d7f6f39cff3460b52aa3f7fdf5 /packages/backend/src | |
| parent | merge: put back buttons "show/hide replies-to-others from all" (!1009) (diff) | |
| download | sharkey-d3a9995d0a252af877f401dc92802fb841291fa1.tar.gz sharkey-d3a9995d0a252af877f401dc92802fb841291fa1.tar.bz2 sharkey-d3a9995d0a252af877f401dc92802fb841291fa1.zip | |
use transaction to avoid unique constraint error when processing duplicate Add/Remove pinned note activities
Diffstat (limited to 'packages/backend/src')
| -rw-r--r-- | packages/backend/src/core/NotePiningService.ts | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/packages/backend/src/core/NotePiningService.ts b/packages/backend/src/core/NotePiningService.ts index 6ab7268254..86f1a62d4a 100644 --- a/packages/backend/src/core/NotePiningService.ts +++ b/packages/backend/src/core/NotePiningService.ts @@ -10,7 +10,7 @@ import { IdentifiableError } from '@/misc/identifiable-error.js'; import type { MiUser } from '@/models/User.js'; import type { MiNote } from '@/models/Note.js'; import { IdService } from '@/core/IdService.js'; -import type { MiUserNotePining } from '@/models/UserNotePining.js'; +import { MiUserNotePining } from '@/models/UserNotePining.js'; import { RelayService } from '@/core/RelayService.js'; import type { Config } from '@/config.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -18,6 +18,7 @@ import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerServ import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; +import type { DataSource } from 'typeorm'; @Injectable() export class NotePiningService { @@ -34,6 +35,9 @@ export class NotePiningService { @Inject(DI.userNotePiningsRepository) private userNotePiningsRepository: UserNotePiningsRepository, + @Inject(DI.db) + private readonly db: DataSource, + private userEntityService: UserEntityService, private idService: IdService, private roleService: RoleService, @@ -60,21 +64,23 @@ export class NotePiningService { throw new IdentifiableError('70c4e51f-5bea-449c-a030-53bee3cce202', 'No such note.'); } - const pinings = await this.userNotePiningsRepository.findBy({ userId: user.id }); + await this.db.transaction(async tem => { + const pinings = await tem.findBy(MiUserNotePining, { userId: user.id }); - if (pinings.length >= (await this.roleService.getUserPolicies(user.id)).pinLimit) { - throw new IdentifiableError('15a018eb-58e5-4da1-93be-330fcc5e4e1a', 'You can not pin notes any more.'); - } + if (pinings.length >= (await this.roleService.getUserPolicies(user.id)).pinLimit) { + throw new IdentifiableError('15a018eb-58e5-4da1-93be-330fcc5e4e1a', 'You can not pin notes any more.'); + } - if (pinings.some(pining => pining.noteId === note.id)) { - throw new IdentifiableError('23f0cf4e-59a3-4276-a91d-61a5891c1514', 'That note has already been pinned.'); - } + if (pinings.some(pining => pining.noteId === note.id)) { + throw new IdentifiableError('23f0cf4e-59a3-4276-a91d-61a5891c1514', 'That note has already been pinned.'); + } - await this.userNotePiningsRepository.insert({ - id: this.idService.gen(), - userId: user.id, - noteId: note.id, - } as MiUserNotePining); + await tem.insert(MiUserNotePining, { + id: this.idService.gen(), + userId: user.id, + noteId: note.id, + }); + }); // Deliver to remote followers if (this.userEntityService.isLocalUser(user) && !note.localOnly && ['public', 'home'].includes(note.visibility)) { |