summaryrefslogtreecommitdiff
path: root/packages/backend/src/server
diff options
context:
space:
mode:
authorMar0xy <marie@kaifa.ch>2023-09-26 02:26:30 +0200
committerMar0xy <marie@kaifa.ch>2023-09-26 02:26:30 +0200
commit8595a325ceb24e5a3e2710c2dc78d821f45181bd (patch)
treeafbce0c498dfd3b324dc30c8dfba847d07117c6a /packages/backend/src/server
parentfix: expiredafter time on poll (diff)
parentbuild(deps): bump actions/checkout from 4.0.0 to 4.1.0 (#11900) (diff)
downloadsharkey-8595a325ceb24e5a3e2710c2dc78d821f45181bd.tar.gz
sharkey-8595a325ceb24e5a3e2710c2dc78d821f45181bd.tar.bz2
sharkey-8595a325ceb24e5a3e2710c2dc78d821f45181bd.zip
merge: upstream
Diffstat (limited to 'packages/backend/src/server')
-rw-r--r--packages/backend/src/server/api/SigninApiService.ts28
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/create.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/delete.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/update.ts7
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/add.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/delete.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/update.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts18
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts1
-rw-r--r--packages/backend/src/server/api/endpoints/admin/queue/clear.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/queue/promote.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/reset-password.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/assign.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/create.ts35
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/delete.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/unassign.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/update.ts17
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/admin/suspend-user.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts15
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-user-note.ts13
-rw-r--r--packages/backend/src/server/api/endpoints/announcements.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/create.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/update.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/drive/files/delete.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/drive/files/update.ts67
-rw-r--r--packages/backend/src/server/api/endpoints/flash/update.ts1
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/done.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/key-done.ts20
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/register-key.ts19
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/register.ts21
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts19
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/unregister.ts20
-rw-r--r--packages/backend/src/server/api/endpoints/i/change-password.ts22
-rw-r--r--packages/backend/src/server/api/endpoints/i/delete-account.ts23
-rw-r--r--packages/backend/src/server/api/endpoints/i/update-email.ts20
-rw-r--r--packages/backend/src/server/api/endpoints/meta.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/notes/delete.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/notes/reactions.ts24
-rw-r--r--packages/backend/src/server/web/ClientServerService.ts4
-rw-r--r--packages/backend/src/server/web/views/base.pug2
44 files changed, 307 insertions, 191 deletions
diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts
index 977a6eb3f2..ef6411250f 100644
--- a/packages/backend/src/server/api/SigninApiService.ts
+++ b/packages/backend/src/server/api/SigninApiService.ts
@@ -20,6 +20,7 @@ import type { MiLocalUser } from '@/models/User.js';
import { IdService } from '@/core/IdService.js';
import { bindThis } from '@/decorators.js';
import { WebAuthnService } from '@/core/WebAuthnService.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
import { RateLimiterService } from './RateLimiterService.js';
import { SigninService } from './SigninService.js';
import type { AuthenticationResponseJSON } from '@simplewebauthn/typescript-types';
@@ -43,6 +44,7 @@ export class SigninApiService {
private idService: IdService,
private rateLimiterService: RateLimiterService,
private signinService: SigninService,
+ private userAuthService: UserAuthService,
private webAuthnService: WebAuthnService,
) {
}
@@ -125,7 +127,7 @@ export class SigninApiService {
const same = await argon2.verify(profile.password!, password);
const fail = async (status?: number, failure?: { id: string }) => {
- // Append signin history
+ // Append signin history
await this.signinsRepository.insert({
id: this.idService.genId(),
createdAt: new Date(),
@@ -155,27 +157,15 @@ export class SigninApiService {
});
}
- if (profile.twoFactorBackupSecret?.includes(token)) {
- await this.userProfilesRepository.update({ userId: profile.userId }, {
- twoFactorBackupSecret: profile.twoFactorBackupSecret.filter((secret) => secret !== token),
- });
- return this.signinService.signin(request, reply, user);
- }
-
- const delta = OTPAuth.TOTP.validate({
- secret: OTPAuth.Secret.fromBase32(profile.twoFactorSecret!),
- digits: 6,
- token,
- window: 1,
- });
-
- if (delta === null) {
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
return await fail(403, {
id: 'cdf1235b-ac71-46d4-a3a6-84ccce48df6f',
});
- } else {
- return this.signinService.signin(request, reply, user);
}
+
+ return this.signinService.signin(request, reply, user);
} else if (body.credential) {
if (!same && !profile.usePasswordLessLogin) {
return await fail(403, {
@@ -204,6 +194,6 @@ export class SigninApiService {
reply.code(200);
return authRequest;
}
- // never get here
+ // never get here
}
}
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 c2f69bb159..262b36b9a4 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
@@ -81,7 +81,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
forExistingUsers: ps.forExistingUsers,
needConfirmationToRead: ps.needConfirmationToRead,
userId: ps.userId,
- });
+ }, me);
return packed;
});
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts
index 80eb6d7a80..80ec281253 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts
@@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { AnnouncementsRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
+import { AnnouncementService } from '@/core/AnnouncementService.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -37,13 +38,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor(
@Inject(DI.announcementsRepository)
private announcementsRepository: AnnouncementsRepository,
+
+ private announcementService: AnnouncementService,
) {
super(meta, paramDef, async (ps, me) => {
const announcement = await this.announcementsRepository.findOneBy({ id: ps.id });
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
- await this.announcementsRepository.delete(announcement.id);
+ await this.announcementService.delete(announcement, me);
});
}
}
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 782928048b..d36590c264 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts
@@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { AnnouncementsRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
+import { AnnouncementService } from '@/core/AnnouncementService.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -45,13 +46,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor(
@Inject(DI.announcementsRepository)
private announcementsRepository: AnnouncementsRepository,
+
+ private announcementService: AnnouncementService,
) {
super(meta, paramDef, async (ps, me) => {
const announcement = await this.announcementsRepository.findOneBy({ id: ps.id });
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
- await this.announcementsRepository.update(announcement.id, {
+ await this.announcementService.update(announcement, {
updatedAt: new Date(),
title: ps.title,
text: ps.text,
@@ -62,7 +65,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
forExistingUsers: ps.forExistingUsers,
needConfirmationToRead: ps.needConfirmationToRead,
isActive: ps.isActive,
- });
+ }, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
index 7bd920c312..24d3a8a943 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
@@ -8,7 +8,6 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import type { DriveFilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
-import { ModerationLogService } from '@/core/ModerationLogService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { ApiError } from '../../../error.js';
@@ -61,7 +60,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private customEmojiService: CustomEmojiService,
private emojiEntityService: EmojiEntityService,
- private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
const driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
@@ -77,11 +75,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSensitive: ps.isSensitive ?? false,
localOnly: ps.localOnly ?? false,
roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [],
- });
-
- this.moderationLogService.insertModerationLog(me, 'addEmoji', {
- emojiId: emoji.id,
- });
+ }, me);
return this.emojiEntityService.packDetailed(emoji);
});
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts
index 4221913049..e6c1bf317f 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts
@@ -30,7 +30,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- await this.customEmojiService.deleteBulk(ps.ids);
+ await this.customEmojiService.deleteBulk(ps.ids, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts
index f020e22182..58aa0b9950 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts
@@ -36,7 +36,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private customEmojiService: CustomEmojiService,
) {
super(meta, paramDef, async (ps, me) => {
- await this.customEmojiService.delete(ps.id);
+ await this.customEmojiService.delete(ps.id, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
index f01be9e27a..2d69857408 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -84,7 +84,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSensitive: ps.isSensitive,
localOnly: ps.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction,
- });
+ }, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts
index fbb91837f2..357bf83e87 100644
--- a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts
+++ b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts
@@ -9,6 +9,7 @@ import type { InstancesRepository } from '@/models/_.js';
import { UtilityService } from '@/core/UtilityService.js';
import { DI } from '@/di-symbols.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
export const meta = {
tags: ['admin'],
@@ -34,6 +35,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private utilityService: UtilityService,
private federatedInstanceService: FederatedInstanceService,
+ private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
const instance = await this.instancesRepository.findOneBy({ host: this.utilityService.toPuny(ps.host) });
@@ -42,9 +44,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new Error('instance not found');
}
- this.federatedInstanceService.update(instance.id, {
+ await this.federatedInstanceService.update(instance.id, {
isSuspended: ps.isSuspended,
});
+
+ if (instance.isSuspended !== ps.isSuspended) {
+ if (ps.isSuspended) {
+ this.moderationLogService.log(me, 'suspendRemoteInstance', {
+ id: instance.id,
+ host: instance.host,
+ });
+ } else {
+ this.moderationLogService.log(me, 'unsuspendRemoteInstance', {
+ id: instance.id,
+ host: instance.host,
+ });
+ }
+ }
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index fe9c134d84..c3ba07cdd0 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -321,6 +321,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
maintainerEmail: instance.maintainerEmail,
version: this.config.version,
name: instance.name,
+ shortName: instance.shortName,
uri: this.config.url,
description: instance.description,
langs: instance.langs,
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts
index b61c580034..c9142e9885 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts
@@ -30,7 +30,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
super(meta, paramDef, async (ps, me) => {
this.queueService.destroy();
- this.moderationLogService.insertModerationLog(me, 'clearQueue');
+ this.moderationLogService.log(me, 'clearQueue');
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/promote.ts b/packages/backend/src/server/api/endpoints/admin/queue/promote.ts
index 8d16cddd00..0cba5b4e25 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/promote.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/promote.ts
@@ -70,7 +70,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
break;
}
- this.moderationLogService.insertModerationLog(me, 'promoteQueue');
+ this.moderationLogService.log(me, 'promoteQueue');
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts
index 8e098e82da..a4a57d8e4e 100644
--- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts
@@ -10,6 +10,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { secureRndstr } from '@/misc/secure-rndstr.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
export const meta = {
tags: ['admin'],
@@ -47,8 +48,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private moderationLogService: ModerationLogService,
) {
- super(meta, paramDef, async (ps) => {
+ super(meta, paramDef, async (ps, me) => {
const user = await this.usersRepository.findOneBy({ id: ps.userId });
if (user == null) {
@@ -70,6 +73,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
password: hash,
});
+ this.moderationLogService.log(me, 'resetPassword', {
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
+ });
+
return {
password: passwd,
};
diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
index 8667640a67..fb5ac7a335 100644
--- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
+++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
@@ -10,6 +10,7 @@ import { InstanceActorService } from '@/core/InstanceActorService.js';
import { QueueService } from '@/core/QueueService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { DI } from '@/di-symbols.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
export const meta = {
tags: ['admin'],
@@ -41,6 +42,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private queueService: QueueService,
private instanceActorService: InstanceActorService,
private apRendererService: ApRendererService,
+ private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId });
@@ -61,6 +63,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
assigneeId: me.id,
forwarded: ps.forward && report.targetUserHost != null,
});
+
+ this.moderationLogService.log(me, 'resolveAbuseReport', {
+ reportId: report.id,
+ report: report,
+ forwarded: ps.forward && report.targetUserHost != null,
+ });
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts
index 9a005982d4..a0f3edd867 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts
@@ -83,7 +83,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return;
}
- await this.roleService.assign(user.id, role.id, ps.expiresAt ? new Date(ps.expiresAt) : null);
+ await this.roleService.assign(user.id, role.id, ps.expiresAt ? new Date(ps.expiresAt) : null, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/create.ts b/packages/backend/src/server/api/endpoints/admin/roles/create.ts
index f567b0d387..8451b1955f 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/create.ts
@@ -5,11 +5,8 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { RolesRepository } from '@/models/_.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
-import { DI } from '@/di-symbols.js';
-import { IdService } from '@/core/IdService.js';
import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
+import { RoleService } from '@/core/RoleService.js';
export const meta = {
tags: ['admin', 'role'],
@@ -58,37 +55,11 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.rolesRepository)
- private rolesRepository: RolesRepository,
-
- private globalEventService: GlobalEventService,
- private idService: IdService,
private roleEntityService: RoleEntityService,
+ private roleService: RoleService,
) {
super(meta, paramDef, async (ps, me) => {
- const date = new Date();
- const created = await this.rolesRepository.insert({
- id: this.idService.genId(),
- createdAt: date,
- updatedAt: date,
- lastUsedAt: date,
- name: ps.name,
- description: ps.description,
- color: ps.color,
- iconUrl: ps.iconUrl,
- target: ps.target,
- condFormula: ps.condFormula,
- isPublic: ps.isPublic,
- isAdministrator: ps.isAdministrator,
- isModerator: ps.isModerator,
- isExplorable: ps.isExplorable,
- asBadge: ps.asBadge,
- canEditMembersByModerator: ps.canEditMembersByModerator,
- displayOrder: ps.displayOrder,
- policies: ps.policies,
- }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0]));
-
- this.globalEventService.publishInternalEvent('roleCreated', created);
+ const created = await this.roleService.create(ps, me);
return await this.roleEntityService.pack(created, me);
});
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/delete.ts b/packages/backend/src/server/api/endpoints/admin/roles/delete.ts
index 6e012f6428..7b989050eb 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/delete.ts
@@ -6,9 +6,9 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { RolesRepository } from '@/models/_.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
+import { RoleService } from '@/core/RoleService.js';
export const meta = {
tags: ['admin', 'role'],
@@ -41,17 +41,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.rolesRepository)
private rolesRepository: RolesRepository,
- private globalEventService: GlobalEventService,
+ private roleService: RoleService,
) {
- super(meta, paramDef, async (ps) => {
+ super(meta, paramDef, async (ps, me) => {
const role = await this.rolesRepository.findOneBy({ id: ps.roleId });
if (role == null) {
throw new ApiError(meta.errors.noSuchRole);
}
- await this.rolesRepository.delete({
- id: ps.roleId,
- });
- this.globalEventService.publishInternalEvent('roleDeleted', role);
+ await this.roleService.delete(role, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts
index 0a79296c05..4c27583111 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts
@@ -81,7 +81,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.noSuchUser);
}
- await this.roleService.unassign(user.id, role.id);
+ await this.roleService.unassign(user.id, role.id, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update.ts b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
index 65fdb4b4b4..6031e2363e 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
@@ -9,6 +9,7 @@ import type { RolesRepository } from '@/models/_.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
+import { RoleService } from '@/core/RoleService.js';
export const meta = {
tags: ['admin', 'role'],
@@ -70,17 +71,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.rolesRepository)
private rolesRepository: RolesRepository,
- private globalEventService: GlobalEventService,
+ private roleService: RoleService,
) {
- super(meta, paramDef, async (ps) => {
- const roleExist = await this.rolesRepository.exist({ where: { id: ps.roleId } });
- if (!roleExist) {
+ super(meta, paramDef, async (ps, me) => {
+ const role = await this.rolesRepository.findOneBy({ id: ps.roleId });
+ if (role == null) {
throw new ApiError(meta.errors.noSuchRole);
}
- const date = new Date();
- await this.rolesRepository.update(ps.roleId, {
- updatedAt: date,
+ await this.roleService.update(role, {
name: ps.name,
description: ps.description,
color: ps.color,
@@ -95,9 +94,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
canEditMembersByModerator: ps.canEditMembersByModerator,
displayOrder: ps.displayOrder,
policies: ps.policies,
- });
- const updated = await this.rolesRepository.findOneByOrFail({ id: ps.roleId });
- this.globalEventService.publishInternalEvent('roleUpdated', updated);
+ }, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts
index d5f97ab149..f87a5a3574 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts
@@ -62,6 +62,8 @@ export const paramDef = {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
+ type: { type: 'string', nullable: true },
+ userId: { type: 'string', format: 'misskey:id', nullable: true },
},
required: [],
} as const;
@@ -78,6 +80,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.moderationLogsRepository.createQueryBuilder('report'), ps.sinceId, ps.untilId);
+ if (ps.type != null) {
+ query.andWhere('report.type = :type', { type: ps.type });
+ }
+
+ if (ps.userId != null) {
+ query.andWhere('report.userId = :userId', { userId: ps.userId });
+ }
+
const reports = await query.limit(ps.limit).getMany();
return await this.moderationLogEntityService.packMany(reports);
diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
index bcf12fa4e8..9464f4b677 100644
--- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
@@ -60,8 +60,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSuspended: true,
});
- this.moderationLogService.insertModerationLog(me, 'suspend', {
- targetId: user.id,
+ this.moderationLogService.log(me, 'suspend', {
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
});
(async () => {
diff --git a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
index 59e89e15bd..5e523bbc31 100644
--- a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
@@ -45,8 +45,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSuspended: false,
});
- this.moderationLogService.insertModerationLog(me, 'unsuspend', {
- targetId: user.id,
+ this.moderationLogService.log(me, 'unsuspend', {
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
});
this.userSuspendService.doPostUnsuspend(user);
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index 614e0a95d7..ea6ebdd1fe 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -44,6 +44,7 @@ export const paramDef = {
backgroundImageUrl: { type: 'string', nullable: true },
logoImageUrl: { type: 'string', nullable: true },
name: { type: 'string', nullable: true },
+ shortName: { type: 'string', nullable: true },
description: { type: 'string', nullable: true },
defaultLightTheme: { type: 'string', nullable: true },
defaultDarkTheme: { type: 'string', nullable: true },
@@ -188,6 +189,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.name = ps.name;
}
+ if (ps.shortName !== undefined) {
+ set.shortName = ps.shortName;
+ }
+
if (ps.description !== undefined) {
set.description = ps.description;
}
@@ -436,8 +441,16 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.manifestJsonOverride = ps.manifestJsonOverride;
}
+ const before = await this.metaService.fetch(true);
+
await this.metaService.update(set);
- this.moderationLogService.insertModerationLog(me, 'updateMeta');
+
+ const after = await this.metaService.fetch(true);
+
+ this.moderationLogService.log(me, 'updateServerSettings', {
+ before,
+ after,
+ });
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
index c86a43977e..bfccc2a2a5 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
@@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import type { UserProfilesRepository, UsersRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
export const meta = {
tags: ['admin'],
@@ -32,6 +33,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
const user = await this.usersRepository.findOneBy({ id: ps.userId });
@@ -40,9 +43,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new Error('user not found');
}
+ const currentProfile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
+
await this.userProfilesRepository.update({ userId: user.id }, {
moderationNote: ps.text,
});
+
+ this.moderationLogService.log(me, 'updateUserNote', {
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
+ before: currentProfile.moderationNote,
+ after: ps.text,
+ });
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts
index 498afe3448..7c242dbcd5 100644
--- a/packages/backend/src/server/api/endpoints/announcements.ts
+++ b/packages/backend/src/server/api/endpoints/announcements.ts
@@ -52,7 +52,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId)
- .where('announcement.isActive = :isActive', { isActive: ps.isActive })
+ .andWhere('announcement.isActive = :isActive', { isActive: ps.isActive })
.andWhere(new Brackets(qb => {
if (me) qb.orWhere('announcement.userId = :meId', { meId: me.id });
qb.orWhere('announcement.userId IS NULL');
diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts
index f1170efe42..15fca4904d 100644
--- a/packages/backend/src/server/api/endpoints/antennas/create.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/create.ts
@@ -47,7 +47,7 @@ export const paramDef = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1, maxLength: 100 },
- src: { type: 'string', enum: ['home', 'all', 'users', 'list'] },
+ src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'users_blacklist'] },
userListId: { type: 'string', format: 'misskey:id', nullable: true },
keywords: { type: 'array', items: {
type: 'array', items: {
diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts
index b020a7595f..0e98746881 100644
--- a/packages/backend/src/server/api/endpoints/antennas/update.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/update.ts
@@ -46,7 +46,7 @@ export const paramDef = {
properties: {
antennaId: { type: 'string', format: 'misskey:id' },
name: { type: 'string', minLength: 1, maxLength: 100 },
- src: { type: 'string', enum: ['home', 'all', 'users', 'list'] },
+ src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'users_blacklist'] },
userListId: { type: 'string', format: 'misskey:id', nullable: true },
keywords: { type: 'array', items: {
type: 'array', items: {
diff --git a/packages/backend/src/server/api/endpoints/drive/files/delete.ts b/packages/backend/src/server/api/endpoints/drive/files/delete.ts
index d7fdc81cdb..f46bf49965 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/delete.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/delete.ts
@@ -65,11 +65,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.accessDenied);
}
- // Delete
- await this.driveService.deleteFile(file);
-
- // Publish fileDeleted event
- this.globalEventService.publishDriveStream(me.id, 'fileDeleted', file.id);
+ await this.driveService.deleteFile(file, false, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts
index d26ed63474..c01f3de03c 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/update.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts
@@ -4,12 +4,11 @@
*/
import { Inject, Injectable } from '@nestjs/common';
-import type { DriveFilesRepository, DriveFoldersRepository } from '@/models/_.js';
+import type { DriveFilesRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
+import { DriveService } from '@/core/DriveService.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -77,16 +76,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository,
- @Inject(DI.driveFoldersRepository)
- private driveFoldersRepository: DriveFoldersRepository,
-
- private driveFileEntityService: DriveFileEntityService,
+ private driveService: DriveService,
private roleService: RoleService,
- private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
- const alwaysMarkNsfw = (await this.roleService.getUserPolicies(me.id)).alwaysMarkNsfw;
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
@@ -95,49 +89,28 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.accessDenied);
}
- if (ps.name) file.name = ps.name;
- if (!this.driveFileEntityService.validateFileName(file.name)) {
- throw new ApiError(meta.errors.invalidFileName);
- }
-
- if (ps.comment !== undefined) file.comment = ps.comment;
-
- if (ps.isSensitive !== undefined && ps.isSensitive !== file.isSensitive && alwaysMarkNsfw && !ps.isSensitive) {
- throw new ApiError(meta.errors.restrictedByRole);
- }
-
- if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive;
+ let packedFile;
- if (ps.folderId !== undefined) {
- if (ps.folderId === null) {
- file.folderId = null;
+ try {
+ packedFile = await this.driveService.updateFile(file, {
+ folderId: ps.folderId,
+ name: ps.name,
+ isSensitive: ps.isSensitive,
+ comment: ps.comment,
+ }, me);
+ } catch (e) {
+ if (e instanceof DriveService.InvalidFileNameError) {
+ throw new ApiError(meta.errors.invalidFileName);
+ } else if (e instanceof DriveService.NoSuchFolderError) {
+ throw new ApiError(meta.errors.noSuchFolder);
+ } else if (e instanceof DriveService.CannotUnmarkSensitiveError) {
+ throw new ApiError(meta.errors.restrictedByRole);
} else {
- const folder = await this.driveFoldersRepository.findOneBy({
- id: ps.folderId,
- userId: me.id,
- });
-
- if (folder == null) {
- throw new ApiError(meta.errors.noSuchFolder);
- }
-
- file.folderId = folder.id;
+ throw e;
}
}
- await this.driveFilesRepository.update(file.id, {
- name: file.name,
- comment: file.comment,
- folderId: file.folderId,
- isSensitive: file.isSensitive,
- });
-
- const fileObj = await this.driveFileEntityService.pack(file, { self: true });
-
- // Publish fileUpdated event
- this.globalEventService.publishDriveStream(me.id, 'fileUpdated', fileObj);
-
- return fileObj;
+ return packedFile;
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/flash/update.ts b/packages/backend/src/server/api/endpoints/flash/update.ts
index cc2c926749..8b5e1f99e9 100644
--- a/packages/backend/src/server/api/endpoints/flash/update.ts
+++ b/packages/backend/src/server/api/endpoints/flash/update.ts
@@ -75,6 +75,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
summary: ps.summary,
script: ps.script,
permissions: ps.permissions,
+ visibility: ps.visibility,
});
});
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/done.ts b/packages/backend/src/server/api/endpoints/i/2fa/done.ts
index c6a193fbb5..9f8e2894b8 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/done.ts
@@ -47,7 +47,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
secret: OTPAuth.Secret.fromBase32(profile.twoFactorTempSecret),
digits: 6,
token,
- window: 1,
+ window: 5,
});
if (delta === null) {
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
index 9591a1f9ec..ac6200632a 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
@@ -13,6 +13,7 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js';
import { WebAuthnService } from '@/core/WebAuthnService.js';
import { ApiError } from '@/server/api/error.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -38,6 +39,7 @@ export const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
+ token: { type: 'string', nullable: true },
name: { type: 'string', minLength: 1, maxLength: 30 },
credential: { type: 'object' },
},
@@ -55,16 +57,28 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private userSecurityKeysRepository: UserSecurityKeysRepository,
private webAuthnService: WebAuthnService,
+ private userAuthService: UserAuthService,
private userEntityService: UserEntityService,
private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
- // Compare password
- const same = await argon2.verify(profile.password ?? '', ps.password);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
- if (!same) {
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
+
+ const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);;
+ if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts
index 0d753df4ce..73ffd6ec68 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts
@@ -11,6 +11,7 @@ import type { UserProfilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { WebAuthnService } from '@/core/WebAuthnService.js';
import { ApiError } from '@/server/api/error.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -42,6 +43,7 @@ export const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
+ token: { type: 'string', nullable: true },
},
required: ['password'],
} as const;
@@ -54,8 +56,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private userProfilesRepository: UserProfilesRepository,
private webAuthnService: WebAuthnService,
+ private userAuthService: UserAuthService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOne({
where: {
userId: me.id,
@@ -68,9 +72,20 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
// Compare password
- const same = await argon2.verify(profile.password ?? '', ps.password);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
- if (!same) {
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
+
+ const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);;
+ if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts
index ee8c0ed1bb..9b3ae74f86 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts
@@ -13,6 +13,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { ApiError } from '@/server/api/error.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -32,6 +33,7 @@ export const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
+ token: { type: 'string', nullable: true },
},
required: ['password'],
} as const;
@@ -44,14 +46,27 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private userAuthService: UserAuthService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
- // Compare password
- const same = await argon2.verify(profile.password ?? '', ps.password);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
+
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
- if (!same) {
+ const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
+ if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
index e63dcbecbe..21e848fb5c 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
@@ -12,6 +12,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -31,6 +32,7 @@ export const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
+ token: { type: 'string', nullable: true },
credentialId: { type: 'string' },
},
required: ['password', 'credentialId'],
@@ -46,15 +48,28 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private userProfilesRepository: UserProfilesRepository,
private userEntityService: UserEntityService,
+ private userAuthService: UserAuthService,
private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
// Compare password
- const same = await argon2.verify(profile.password ?? '', ps.password);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
- if (!same) {
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
+
+ const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
+ if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
index 0f72edef25..8dd880c9fa 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
@@ -12,6 +12,7 @@ import type { UserProfilesRepository } from '@/models/_.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -31,6 +32,7 @@ export const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
+ token: { type: 'string', nullable: true },
},
required: ['password'],
} as const;
@@ -42,15 +44,27 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private userProfilesRepository: UserProfilesRepository,
private userEntityService: UserEntityService,
+ private userAuthService: UserAuthService,
private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
- // Compare password
- const same = await argon2.verify(profile.password ?? '', ps.password);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
- if (!same) {
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
+
+ const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
+ if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts
index ac28a28946..fb0f2bc88e 100644
--- a/packages/backend/src/server/api/endpoints/i/change-password.ts
+++ b/packages/backend/src/server/api/endpoints/i/change-password.ts
@@ -9,6 +9,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UserProfilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -21,6 +22,7 @@ export const paramDef = {
properties: {
currentPassword: { type: 'string' },
newPassword: { type: 'string', minLength: 1 },
+ token: { type: 'string', nullable: true },
},
required: ['currentPassword', 'newPassword'],
} as const;
@@ -30,14 +32,28 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor(
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private userAuthService: UserAuthService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
- // Compare password
- const same = await argon2.verify(profile.password!, ps.currentPassword);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
+
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
+
+ const passwordMatched = await argon2.verify(profile.password!, ps.currentPassword);
- if (!same) {
+ if (!passwordMatched) {
throw new Error('incorrect password');
}
diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts
index 7c96d94706..e0b40db917 100644
--- a/packages/backend/src/server/api/endpoints/i/delete-account.ts
+++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts
@@ -10,6 +10,7 @@ import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DeleteAccountService } from '@/core/DeleteAccountService.js';
import { DI } from '@/di-symbols.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
export const meta = {
requireCredential: true,
@@ -21,6 +22,7 @@ export const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
+ token: { type: 'string', nullable: true },
},
required: ['password'],
} as const;
@@ -34,19 +36,32 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+ private userAuthService: UserAuthService,
private deleteAccountService: DeleteAccountService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
+
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
+
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
+
const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id });
if (userDetailed.isDeleted) {
return;
}
- // Compare password
- const same = await argon2.verify(profile.password!, ps.password);
-
- if (!same) {
+ const passwordMatched = await argon2.verify(profile.password!, ps.password);
+ if (!passwordMatched) {
throw new Error('incorrect password');
}
diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts
index 19a034af93..78000fca51 100644
--- a/packages/backend/src/server/api/endpoints/i/update-email.ts
+++ b/packages/backend/src/server/api/endpoints/i/update-email.ts
@@ -15,6 +15,7 @@ import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js';
+import { UserAuthService } from '@/core/UserAuthService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -47,6 +48,7 @@ export const paramDef = {
properties: {
password: { type: 'string' },
email: { type: 'string', nullable: true },
+ token: { type: 'string', nullable: true },
},
required: ['password'],
} as const;
@@ -62,15 +64,27 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private userEntityService: UserEntityService,
private emailService: EmailService,
+ private userAuthService: UserAuthService,
private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
+ const token = ps.token;
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
- // Compare password
- const same = await argon2.verify(profile.password!, ps.password);
+ if (profile.twoFactorEnabled) {
+ if (token == null) {
+ throw new Error('authentication failed');
+ }
+
+ try {
+ await this.userAuthService.twoFactorAuthenticate(profile, token);
+ } catch (e) {
+ throw new Error('authentication failed');
+ }
+ }
- if (!same) {
+ const passwordMatched = await argon2.verify(profile.password!, ps.password);;
+ if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index c0cbfa3f48..fa6486ed18 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -40,6 +40,10 @@ export const meta = {
type: 'string',
optional: false, nullable: false,
},
+ shortName: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
uri: {
type: 'string',
optional: false, nullable: false,
@@ -288,6 +292,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
version: this.config.version,
name: instance.name,
+ shortName: instance.shortName,
uri: this.config.url,
description: instance.description,
langs: instance.langs,
diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts
index 74062a58f5..55aaaf4f78 100644
--- a/packages/backend/src/server/api/endpoints/notes/delete.ts
+++ b/packages/backend/src/server/api/endpoints/notes/delete.ts
@@ -70,7 +70,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
// この操作を行うのが投稿者とは限らない(例えばモデレーター)ため
- await this.noteDeleteService.delete(await this.usersRepository.findOneByOrFail({ id: note.userId }), note);
+ await this.noteDeleteService.delete(await this.usersRepository.findOneByOrFail({ id: note.userId }), note, false, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts
index dae31364ee..a2c1778199 100644
--- a/packages/backend/src/server/api/endpoints/notes/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts
@@ -4,12 +4,13 @@
*/
import { Inject, Injectable } from '@nestjs/common';
+import { Brackets, type FindOptionsWhere } from 'typeorm';
import type { NoteReactionsRepository } from '@/models/_.js';
import type { MiNoteReaction } from '@/models/NoteReaction.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteReactionEntityService } from '@/core/entities/NoteReactionEntityService.js';
import { DI } from '@/di-symbols.js';
-import type { FindOptionsWhere } from 'typeorm';
+import { QueryService } from '@/core/QueryService.js';
export const meta = {
tags: ['notes', 'reactions'],
@@ -44,7 +45,6 @@ export const paramDef = {
noteId: { type: 'string', format: 'misskey:id' },
type: { type: 'string', nullable: true },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
- offset: { type: 'integer', default: 0 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
@@ -58,29 +58,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private noteReactionsRepository: NoteReactionsRepository,
private noteReactionEntityService: NoteReactionEntityService,
+ private queryService: QueryService,
) {
super(meta, paramDef, async (ps, me) => {
- const query = {
- noteId: ps.noteId,
- } as FindOptionsWhere<MiNoteReaction>;
+ const query = this.queryService.makePaginationQuery(this.noteReactionsRepository.createQueryBuilder('reaction'), ps.sinceId, ps.untilId)
+ .andWhere('reaction.noteId = :noteId', { noteId: ps.noteId })
+ .leftJoinAndSelect('reaction.user', 'user')
+ .leftJoinAndSelect('reaction.note', 'note');
if (ps.type) {
// ローカルリアクションはホスト名が . とされているが
// DB 上ではそうではないので、必要に応じて変換
const suffix = '@.:';
const type = ps.type.endsWith(suffix) ? ps.type.slice(0, ps.type.length - suffix.length) + ':' : ps.type;
- query.reaction = type;
+ query.andWhere('reaction.reaction = :type', { type });
}
- const reactions = await this.noteReactionsRepository.find({
- where: query,
- take: ps.limit,
- skip: ps.offset,
- order: {
- id: -1,
- },
- relations: ['user', 'note'],
- });
+ const reactions = await query.limit(ps.limit).getMany();
return await Promise.all(reactions.map(reaction => this.noteReactionEntityService.pack(reaction, me)));
});
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index 7b1dd92d73..1faff24201 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -114,10 +114,10 @@ export class ClientServerService {
let manifest = {
// 空文字列の場合右辺を使いたいため
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- 'short_name': instance.name || 'Misskey',
+ 'short_name': instance.shortName || instance.name || this.config.host,
// 空文字列の場合右辺を使いたいため
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- 'name': instance.name || 'Misskey',
+ 'name': instance.name || this.config.host,
'start_url': '/',
'display': 'standalone',
'background_color': '#313a42',
diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug
index ab74a1f7f4..71bcf9462f 100644
--- a/packages/backend/src/server/web/views/base.pug
+++ b/packages/backend/src/server/web/views/base.pug
@@ -35,7 +35,7 @@ html
link(rel='prefetch' href=infoImageUrl)
link(rel='prefetch' href=notFoundImageUrl)
//- https://github.com/misskey-dev/misskey/issues/9842
- link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.32.0')
+ link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.35.0')
link(rel='modulepreload' href=`/vite/${clientEntry.file}`)
if !config.clientManifestExists