From d9f7ac0335a743475e7d6e185b2a561a3f504464 Mon Sep 17 00:00:00 2001 From: Vavency Date: Thu, 10 Apr 2025 21:31:38 +0300 Subject: [PATCH 001/145] [frontend] WIP slice optimization Very broken. --- .../frontend/src/components/SkModPlayer.vue | 345 +++++++++++++----- 1 file changed, 248 insertions(+), 97 deletions(-) diff --git a/packages/frontend/src/components/SkModPlayer.vue b/packages/frontend/src/components/SkModPlayer.vue index 0933806109..9ce4d36be7 100644 --- a/packages/frontend/src/components/SkModPlayer.vue +++ b/packages/frontend/src/components/SkModPlayer.vue @@ -17,9 +17,14 @@ SPDX-License-Identifier: AGPL-3.0-only Pattern Hidden {{ i18n.ts.clickToShow }} + +
+ +
@@ -41,6 +46,13 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index c2a886a18c..19cbe30fde 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -6694,6 +6694,8 @@ export type operations = { display?: 'normal' | 'banner' | 'dialog'; /** @default false */ forExistingUsers?: boolean; + /** @default null */ + forRoles?: string[] | null; /** @default false */ silence?: boolean; /** @default false */ @@ -6856,6 +6858,7 @@ export type operations = { title: string; imageUrl: string | null; reads: number; + forRoles: string[] | null; })[]; }; }; @@ -6911,6 +6914,8 @@ export type operations = { /** @enum {string} */ display?: 'normal' | 'banner' | 'dialog'; forExistingUsers?: boolean; + /** @default null */ + forRoles?: string[] | null; silence?: boolean; needConfirmationToRead?: boolean; confetti?: boolean; diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml index d8602a1489..4ae753d973 100644 --- a/sharkey-locales/en-US.yml +++ b/sharkey-locales/en-US.yml @@ -479,6 +479,10 @@ _auth: allowed: "Allowed" _announcement: new: "New" + onlyForRoles: "Restrict to roles" + onlyForRolesChange: "Change role restrictions" + onlyForRolesUnrestricted: "Shown to everyone" + onlyForRolesRestricted: "Shown to members of {roles} roles" confetti: "Throw confetti" confettiDescription: "If enabled, the announcement will display a confetti effect when viewed." _deck: From b61c1d5b27f8381c0ed7d04fa824c68c7db0a444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Tue, 22 Jul 2025 00:26:05 +0200 Subject: [PATCH 137/145] forRoles IS NOT NULL, coalesce to empty=unrestricted --- .../migration/1752352800438-announcement-forRoles.js | 2 +- packages/backend/src/core/AnnouncementService.ts | 2 +- packages/backend/src/models/Announcement.ts | 4 ++-- .../server/api/endpoints/admin/announcements/create.ts | 2 +- .../server/api/endpoints/admin/announcements/list.ts | 2 +- .../server/api/endpoints/admin/announcements/update.ts | 2 +- .../backend/src/server/api/endpoints/announcements.ts | 2 +- packages/frontend/src/pages/admin/announcements.vue | 6 +++--- packages/misskey-js/src/autogen/types.ts | 10 +++++----- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/backend/migration/1752352800438-announcement-forRoles.js b/packages/backend/migration/1752352800438-announcement-forRoles.js index a148c87eed..a3fcb449c5 100644 --- a/packages/backend/migration/1752352800438-announcement-forRoles.js +++ b/packages/backend/migration/1752352800438-announcement-forRoles.js @@ -5,7 +5,7 @@ export class AnnouncementForRoles1752352800438 { async up(queryRunner) { - await queryRunner.query(`ALTER TABLE "announcement" ADD "forRoles" text[] DEFAULT null`); + await queryRunner.query(`ALTER TABLE "announcement" ADD "forRoles" text[] DEFAULT '{}'`); } async down(queryRunner) { diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts index 643f0c7e05..616cd710fa 100644 --- a/packages/backend/src/core/AnnouncementService.ts +++ b/packages/backend/src/core/AnnouncementService.ts @@ -63,7 +63,7 @@ export class AnnouncementService { })) .andWhere(new Brackets(qb => { qb.orWhere('announcement.forRoles && :roles', { roles: roles.map((r) => r.id) }); - qb.orWhere('announcement.forRoles IS NULL'); + qb.orWhere('announcement.forRoles = \'{}\''); })) .andWhere(`announcement.id NOT IN (${ readsQuery.getQuery() })`); diff --git a/packages/backend/src/models/Announcement.ts b/packages/backend/src/models/Announcement.ts index 2e0fb66137..15857bcb92 100644 --- a/packages/backend/src/models/Announcement.ts +++ b/packages/backend/src/models/Announcement.ts @@ -69,9 +69,9 @@ export class MiAnnouncement { @Column('text', { array: true, - default: null, nullable: true, + default: '{}', nullable: false, }) - public forRoles: MiRole['id'][] | null; + public forRoles: MiRole['id'][]; @Index() @Column('boolean', { diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts index c37b54b9c9..76acf5440d 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts @@ -59,7 +59,7 @@ export const paramDef = { icon: { type: 'string', enum: ['info', 'warning', 'error', 'success'], default: 'info' }, display: { type: 'string', enum: ['normal', 'banner', 'dialog'], default: 'normal' }, forExistingUsers: { type: 'boolean', default: false }, - forRoles: { type: 'array', nullable: true, default: null, items: { type: 'string', nullable: false, format: 'misskey:id' }, }, + forRoles: { type: 'array', default: [], items: { type: 'string', nullable: false, format: 'misskey:id' }, }, silence: { type: 'boolean', default: false }, needConfirmationToRead: { type: 'boolean', default: false }, confetti: { type: 'boolean', default: false }, diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts index 9fbd46d7b2..6bd3989df5 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts @@ -59,7 +59,7 @@ export const meta = { }, forRoles: { type: 'array', - optional: false, nullable: true, + optional: false, nullable: false, items: { type: 'string', optional: false, nullable: false, diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts index 4132647969..f694b64dd8 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts @@ -36,7 +36,7 @@ export const paramDef = { icon: { type: 'string', enum: ['info', 'warning', 'error', 'success'] }, display: { type: 'string', enum: ['normal', 'banner', 'dialog'] }, forExistingUsers: { type: 'boolean' }, - forRoles: { type: 'array', nullable: true, default: null, items: { type: 'string', nullable: false, format: 'misskey:id' }, }, + forRoles: { type: 'array', default: [], items: { type: 'string', nullable: false, format: 'misskey:id' }, }, silence: { type: 'boolean' }, needConfirmationToRead: { type: 'boolean' }, confetti: { type: 'boolean' }, diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts index 3ac7173d8c..08528ce826 100644 --- a/packages/backend/src/server/api/endpoints/announcements.ts +++ b/packages/backend/src/server/api/endpoints/announcements.ts @@ -65,7 +65,7 @@ export default class extends Endpoint { // eslint- })) .andWhere(new Brackets(qb => { if (me) qb.orWhere('announcement.forRoles && :roles', { roles: roles.map((r) => r.id) }); - qb.orWhere('announcement.forRoles IS NULL'); + qb.orWhere('announcement.forRoles = \'{}\''); })); const announcements = await query.limit(ps.limit).getMany(); diff --git a/packages/frontend/src/pages/admin/announcements.vue b/packages/frontend/src/pages/admin/announcements.vue index 3dd4ee8fb4..67a8a6ed89 100644 --- a/packages/frontend/src/pages/admin/announcements.vue +++ b/packages/frontend/src/pages/admin/announcements.vue @@ -76,7 +76,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.tsx._announcement.onlyForRolesRestricted({roles: announcement.forRoles.length}) }} + {{ i18n.tsx._announcement.onlyForRolesRestricted({roles: announcement.forRoles.length}) }} {{ i18n.ts._announcement.onlyForRolesUnrestricted }} {{ i18n.ts._announcement.onlyForRolesChange }} @@ -141,7 +141,7 @@ function add() { silence: false, needConfirmationToRead: false, confetti: false, - forRoles: null, + forRoles: [], }); } @@ -153,7 +153,7 @@ async function changeRoles(announcement) { }); if (result.canceled) return; - announcement.forRoles = result.result.length !== 0 ? result.result.map((r) => r.id) : null; + announcement.forRoles = result.result.map((r) => r.id); } function del(announcement) { diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 19cbe30fde..7a1f2daa58 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -6694,8 +6694,8 @@ export type operations = { display?: 'normal' | 'banner' | 'dialog'; /** @default false */ forExistingUsers?: boolean; - /** @default null */ - forRoles?: string[] | null; + /** @default [] */ + forRoles?: string[]; /** @default false */ silence?: boolean; /** @default false */ @@ -6858,7 +6858,7 @@ export type operations = { title: string; imageUrl: string | null; reads: number; - forRoles: string[] | null; + forRoles: string[]; })[]; }; }; @@ -6914,8 +6914,8 @@ export type operations = { /** @enum {string} */ display?: 'normal' | 'banner' | 'dialog'; forExistingUsers?: boolean; - /** @default null */ - forRoles?: string[] | null; + /** @default [] */ + forRoles?: string[]; silence?: boolean; needConfirmationToRead?: boolean; confetti?: boolean; From 132c25b2711ef1c08d4cb849e5526a4f3846d04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sun, 13 Jul 2025 06:15:45 +0200 Subject: [PATCH 138/145] Log IP addresses used during registration Closes #836 --- .../migration/1752377661219-UserPending-ip.js | 14 ++++++++ packages/backend/src/models/UserPending.ts | 6 ++++ .../src/server/api/SignupApiService.ts | 35 ++++++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 packages/backend/migration/1752377661219-UserPending-ip.js diff --git a/packages/backend/migration/1752377661219-UserPending-ip.js b/packages/backend/migration/1752377661219-UserPending-ip.js new file mode 100644 index 0000000000..12e5d6cc3e --- /dev/null +++ b/packages/backend/migration/1752377661219-UserPending-ip.js @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: наб and other Sharkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class UserPendingIp1752377661219 { + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_pending" ADD "requestOriginIp" varchar(128)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_pending" DROP COLUMN "requestOriginIp"`); + } +} diff --git a/packages/backend/src/models/UserPending.ts b/packages/backend/src/models/UserPending.ts index 972c862a1a..2b4d5ac329 100644 --- a/packages/backend/src/models/UserPending.ts +++ b/packages/backend/src/models/UserPending.ts @@ -37,4 +37,10 @@ export class MiUserPending { nullable: true, }) public reason: string; + + @Column('varchar', { + length: 128, + nullable: true, + }) + public requestOriginIp: string | null; } diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index c1864ce959..590ce44e5b 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as argon2 from 'argon2'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket, MiMeta } from '@/models/_.js'; +import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket, MiMeta, UserIpsRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { CaptchaService } from '@/core/CaptchaService.js'; import { IdService } from '@/core/IdService.js'; @@ -46,6 +46,9 @@ export class SignupApiService { @Inject(DI.registrationTicketsRepository) private registrationTicketsRepository: RegistrationTicketsRepository, + @Inject(DI.userIpsRepository) + private userIpsRepository: UserIpsRepository, + private userEntityService: UserEntityService, private idService: IdService, private captchaService: CaptchaService, @@ -213,6 +216,7 @@ export class SignupApiService { username: username, password: hash, reason: reason, + requestOriginIp: this.meta.enableIpLogging ? request.ip : null, }); const link = `${this.config.url}/signup-complete/${code}`; @@ -249,6 +253,10 @@ export class SignupApiService { }); } + if (this.meta.enableIpLogging) { + this.logIp(request.ip, null, account.id); + } + const moderators = await this.roleService.getModerators(); for (const moderator of moderators) { @@ -282,6 +290,10 @@ export class SignupApiService { }); } + if (this.meta.enableIpLogging) { + this.logIp(request.ip, null, account.id); + } + return { ...res, token: secret, @@ -332,6 +344,15 @@ export class SignupApiService { }); } + if (pendingUser.requestOriginIp) { + this.logIp(pendingUser.requestOriginIp, this.idService.parse(pendingUser.id).date, account.id); + } + + // The sign-up request and the confirmation may've come from different addresses: log both + if (this.meta.enableIpLogging) { + this.logIp(request.ip, null, account.id); + } + if (this.meta.approvalRequiredForSignup) { if (pendingUser.email) { this.emailService.sendEmail(pendingUser.email, 'Approval pending', @@ -359,4 +380,16 @@ export class SignupApiService { throw new FastifyReplyError(400, String(err), err); } } + + @bindThis + private logIp(ip: string, ipDate: Date | null, userId: MiLocalUser['id']) { + try { + this.userIpsRepository.createQueryBuilder().insert().values({ + createdAt: ipDate ?? new Date(), + userId, + ip, + }).orIgnore(true).execute(); + } catch { + } + } } From e22ae591b6757a147f28c968468aff54f81c0930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Mon, 21 Jul 2025 21:22:38 +0200 Subject: [PATCH 139/145] SignupApiService: logIp() additional logging --- packages/backend/src/server/api/SignupApiService.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 590ce44e5b..86896264dd 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -19,11 +19,14 @@ import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; import { bindThis } from '@/decorators.js'; import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js'; import { RoleService } from '@/core/RoleService.js'; +import Logger from '@/logger.js'; +import { LoggerService } from '@/core/LoggerService.js'; import { SigninService } from './SigninService.js'; import type { FastifyRequest, FastifyReply } from 'fastify'; @Injectable() export class SignupApiService { + private logger: Logger; constructor( @Inject(DI.config) private config: Config, @@ -56,7 +59,9 @@ export class SignupApiService { private signinService: SigninService, private emailService: EmailService, private roleService: RoleService, + private loggerService: LoggerService, ) { + this.logger = this.loggerService.getLogger('Signup'); } @bindThis @@ -389,7 +394,8 @@ export class SignupApiService { userId, ip, }).orIgnore(true).execute(); - } catch { + } catch (err) { + this.logger.error(err as Error); } } } From 5aceeb31e7b1fd72a5e05cebc9a2e3d4584d4f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Wed, 16 Jul 2025 01:04:06 +0200 Subject: [PATCH 140/145] Return request errors for /streaming in-band instead of in HTTP Closes #591 --- .../server/api/StreamingApiServerService.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 231ba7bfbf..b6b930a434 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -116,6 +116,7 @@ export class StreamingApiServerService implements OnApplicationShutdown { let user: MiLocalUser | null = null; let app: MiAccessToken | null = null; + let dieInstantly: [number, string] | null = null; // https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 // Note that the standard WHATWG WebSocket API does not support setting any headers, @@ -132,21 +133,16 @@ export class StreamingApiServerService implements OnApplicationShutdown { } } catch (e) { if (e instanceof AuthenticationError) { - socket.write([ - 'HTTP/1.1 401 Unauthorized', - 'WWW-Authenticate: Bearer realm="Misskey", error="invalid_token", error_description="Failed to authenticate"', - ].join('\r\n') + '\r\n\r\n'); + dieInstantly = [4000, 'Failed to authenticate']; } else { socket.write('HTTP/1.1 500 Internal Server Error\r\n\r\n'); + socket.destroy(); + return; } - socket.destroy(); - return; } if (user?.isSuspended) { - socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); - socket.destroy(); - return; + dieInstantly = [4001, 'User suspended']; } // ServerServices sets `trustProxy: true`, which inside fastify/request.js ends up calling `proxyAddr` in this way, so we do the same. @@ -231,6 +227,11 @@ export class StreamingApiServerService implements OnApplicationShutdown { ws.terminate(); }); + if (dieInstantly !== null) { + ws.close(...dieInstantly); + return; + } + this.#wss.emit('connection', ws, request, { stream, user, app, }); From 155d2920b637f76a10d66cb5c3d5aa3e8dec0eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Wed, 16 Jul 2025 18:43:00 +0200 Subject: [PATCH 141/145] Dispose of the stream even if it gets closed early --- packages/backend/src/server/api/StreamingApiServerService.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index b6b930a434..783f6af34e 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -220,6 +220,8 @@ export class StreamingApiServerService implements OnApplicationShutdown { if (connectionsForClient.size < 1) { this.#connectionsByClient.delete(limitActor); } + + stream.dispose(); }); ws.once('error', (e) => { From 93488f862cda112e59cdbe354b4c5c9989b216b7 Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 12 Aug 2025 18:55:24 +0000 Subject: [PATCH 142/145] Fix .gitlab-ci.yml --- .gitlab-ci.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b11ea613ce..201fceccc1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -120,19 +120,18 @@ merge_image_manifests: artifacts: false - job: get_image_tag artifacts: true - image: docker.io/alpine:latest image: name: mplatform/manifest-tool:alpine entrypoint: [""] script: - >- - manifest-tool - --username=${CI_REGISTRY_USER} - --password=${CI_REGISTRY_PASSWORD} - push from-args - --platforms linux/amd64,linux/arm64 - --tags ${REGISTRY_PUSH_VERSION} - --template ${CI_REGISTRY_IMAGE}:${REGISTRY_PUSH_VERSION}-ARCH + manifest-tool \ + --username=${CI_REGISTRY_USER} \ + --password=${CI_REGISTRY_PASSWORD} \ + push from-args \ + --platforms linux/amd64,linux/arm64 \ + --tags ${REGISTRY_PUSH_VERSION} \ + --template ${CI_REGISTRY_IMAGE}:${REGISTRY_PUSH_VERSION}-ARCH \ --target ${CI_REGISTRY_IMAGE}:${REGISTRY_PUSH_TAG} only: - stable From 1695f4c8001fb5af75193b2450a6f1ae956ed1d7 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Wed, 13 Aug 2025 23:10:57 -0400 Subject: [PATCH 143/145] pass -map 0 to preserve all streams --- packages/backend/src/core/VideoProcessingService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/core/VideoProcessingService.ts b/packages/backend/src/core/VideoProcessingService.ts index 3e4fd6a4b0..8f4d6cc189 100644 --- a/packages/backend/src/core/VideoProcessingService.ts +++ b/packages/backend/src/core/VideoProcessingService.ts @@ -102,6 +102,7 @@ export class VideoProcessingService { .format(outputFormat) // Specify output format .addOutputOptions('-c copy') // Copy streams without re-encoding .addOutputOptions('-movflags +faststart') + .addOutputOptions('-map 0') .on('error', reject) .on('end', async () => { try { From a92d3ca12160989a2dba5ace71a22b9098bc96d3 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Wed, 13 Aug 2025 23:54:09 -0400 Subject: [PATCH 144/145] delete any "new chat" notifications when deleting rooms --- packages/backend/src/core/ChatService.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index 9d294a80cb..62cf04e00e 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -580,11 +580,20 @@ export class ChatService { public async deleteRoom(room: MiChatRoom, deleter?: MiUser) { await this.chatRoomsRepository.delete(room.id); + // Erase any message notifications for this room + const redisPipeline = this.redisClient.pipeline(); + const memberships = await this.chatRoomMembershipsRepository.findBy({ roomId: room.id }); + for (const membership of memberships) { + redisPipeline.del(`newRoomChatMessageExists:${membership.userId}:${room.id}`); + redisPipeline.srem(`newChatMessagesExists:${membership.userId}`, `room:${room.id}`); + } + await redisPipeline.exec(); + if (deleter) { const deleterIsModerator = await this.roleService.isModerator(deleter); if (deleterIsModerator) { - this.moderationLogService.log(deleter, 'deleteChatRoom', { + await this.moderationLogService.log(deleter, 'deleteChatRoom', { roomId: room.id, room: room, }); From 521d7d0cf3cdcf5c8c18f23ed661de2d1e899226 Mon Sep 17 00:00:00 2001 From: Lillychan Date: Sun, 31 Aug 2025 11:41:05 +0200 Subject: [PATCH 145/145] Update file 1754754816000-metaRulesLength.js --- packages/backend/migration/1754754816000-metaRulesLength.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/migration/1754754816000-metaRulesLength.js b/packages/backend/migration/1754754816000-metaRulesLength.js index b63aa1bb0a..2f010789d2 100644 --- a/packages/backend/migration/1754754816000-metaRulesLength.js +++ b/packages/backend/migration/1754754816000-metaRulesLength.js @@ -5,10 +5,10 @@ export class MetaRulesLength1754754816000 { async up(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "serverRules" TYPE TEXT`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "serverRules" TYPE TEXT[]`); } async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "serverRules" TYPE character varying(280)`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "serverRules" TYPE character varying(280)[]`); } }