lint and type fixes

This commit is contained in:
Hazelnoot 2025-04-01 20:47:04 -04:00
parent 54071efaea
commit 6ac37b4d6c
84 changed files with 188 additions and 374 deletions

View file

@ -1,107 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import Limiter from 'ratelimiter';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
import type Logger from '@/logger.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import { LegacyRateLimit } from '@/misc/rate-limit-utils.js';
import type { IEndpointMeta } from './endpoints.js';
/** @deprecated Use SkRateLimiterService instead */
@Injectable()
export class RateLimiterService {
private logger: Logger;
private disabled = false;
constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
private loggerService: LoggerService,
) {
this.logger = this.loggerService.getLogger('limiter');
if (process.env.NODE_ENV !== 'production') {
this.disabled = true;
}
}
@bindThis
public limit(limitation: LegacyRateLimit & { key: NonNullable<string> }, actor: string, factor = 1) {
return new Promise<void>((ok, reject) => {
if (this.disabled) ok();
// Short-term limit
const minP = (): void => {
const minIntervalLimiter = new Limiter({
id: `${actor}:${limitation.key}:min`,
duration: limitation.minInterval! * factor,
max: 1,
db: this.redisClient,
});
minIntervalLimiter.get((err, info) => {
if (err) {
return reject({ code: 'ERR', info });
}
this.logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);
if (info.remaining === 0) {
return reject({ code: 'BRIEF_REQUEST_INTERVAL', info });
} else {
if (hasLongTermLimit) {
return maxP();
} else {
return ok();
}
}
});
};
// Long term limit
const maxP = (): void => {
const limiter = new Limiter({
id: `${actor}:${limitation.key}`,
duration: limitation.duration! * factor,
max: limitation.max! / factor,
db: this.redisClient,
});
limiter.get((err, info) => {
if (err) {
return reject({ code: 'ERR', info });
}
this.logger.debug(`${actor} ${limitation.key} max remaining: ${info.remaining}`);
if (info.remaining === 0) {
return reject({ code: 'RATE_LIMIT_EXCEEDED', info });
} else {
return ok();
}
});
};
const hasShortTermLimit = typeof limitation.minInterval === 'number';
const hasLongTermLimit =
typeof limitation.duration === 'number' &&
typeof limitation.max === 'number';
if (hasShortTermLimit) {
minP();
} else if (hasLongTermLimit) {
maxP();
} else {
ok();
}
});
}
}

View file

@ -35,7 +35,8 @@ import type { FastifyReply, FastifyRequest } from 'fastify';
// Up to 10 attempts, then 1 per minute
const signinRateLimit: Keyed<RateLimit> = {
key: 'signin',
max: 10,
type: 'bucket',
size: 10,
dripRate: 1000 * 60,
};
@ -146,7 +147,7 @@ export class SigninApiService {
if (isSystemAccount(user)) {
return error(403, {
id: 's8dhsj9s-a93j-493j-ja9k-kas9sj20aml2',
id: 'ba4ba3bc-ef1e-4c74-ad88-1d2b7d69a100',
});
}
@ -243,7 +244,7 @@ export class SigninApiService {
if (profile.password!.startsWith('$2')) {
const newHash = await argon2.hash(password);
this.userProfilesRepository.update(user.id, {
password: newHash
password: newHash,
});
}
if (!this.meta.approvalRequiredForSignup && !user.approved) this.usersRepository.update(user.id, { approved: true });
@ -267,7 +268,7 @@ export class SigninApiService {
if (profile.password!.startsWith('$2')) {
const newHash = await argon2.hash(password);
this.userProfilesRepository.update(user.id, {
password: newHash
password: newHash,
});
}
await this.userAuthService.twoFactorAuthenticate(profile, token);

View file

@ -4,7 +4,6 @@
*/
import { Inject, Injectable } from '@nestjs/common';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
@ -205,7 +204,6 @@ export class SignupApiService {
const code = secureRndstr(16, { chars: L_CHARS });
// Generate hash of password
//const salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(password);
const pendingUser = await this.userPendingsRepository.insertOne({

View file

@ -124,9 +124,11 @@ export class StreamingApiServerService {
const requestIp = proxyAddr(request, () => true );
const limitActor = user?.id ?? getIpHash(requestIp);
if (await this.rateLimitThis(limitActor, {
// Up to 32 connections, then 1 every 10 seconds
type: 'bucket',
key: 'wsconnect',
duration: ms('5min'),
max: 32,
size: 32,
dripRate: 10 * 1000,
})) {
socket.write('HTTP/1.1 429 Rate Limit Exceeded\r\n\r\n');
socket.destroy();

View file

@ -33,7 +33,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private readonly driveFilesRepository: DriveFilesRepository,
) {
super(meta, paramDef, async (ps, me) => {
const file = await driveFilesRepository.findOneByOrFail({ id: ps.fileId });
const file = await this.driveFilesRepository.findOneByOrFail({ id: ps.fileId });
await this.moderationLogService.log(me, 'importCustomEmojis', {
fileName: file.name,
});

View file

@ -26,7 +26,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) {
super(meta, paramDef, async (ps, me) => {
const keys = await generateVAPIDKeys();
// TODO add moderation log
return { public: keys.publicKey, private: keys.privateKey };
});
}

View file

@ -4,7 +4,6 @@
*/
import { Inject, Injectable } from '@nestjs/common';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UsersRepository, UserProfilesRepository, MiMeta } from '@/models/_.js';

View file

@ -404,14 +404,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.turnstileSecretKey = ps.turnstileSecretKey;
}
if (ps.enableFC !== undefined) {
set.enableFC = ps.enableFC;
}
if (ps.enableTestcaptcha !== undefined) {
set.enableTestcaptcha = ps.enableTestcaptcha;
}
if (ps.enableFC !== undefined) {
set.enableFC = ps.enableFC;
}
if (ps.fcSiteKey !== undefined) {
set.fcSiteKey = ps.fcSiteKey;
}

View file

@ -30,7 +30,8 @@ export const meta = {
// Up to 30 calls, then 1 per 1/2 second
limit: {
max: 30,
type: 'bucket',
size: 30,
dripRate: 500,
},

View file

@ -16,7 +16,8 @@ export const meta = {
// Up to 10 calls, then 4 / second.
// This allows for reliable automation.
limit: {
max: 10,
type: 'bucket',
size: 10,
dripRate: 250,
},
} as const;

View file

@ -34,7 +34,8 @@ export const meta = {
// up to 20 calls, then 1 per second.
// This handles bursty traffic when all tabs reload as a group
limit: {
max: 20,
type: 'bucket',
size: 20,
dripSize: 1,
dripRate: 1000,
},

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import * as OTPAuth from 'otpauth';
import * as QRCode from 'qrcode';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';
import { Endpoint } from '@/server/api/endpoint-base.js';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';
@ -65,7 +64,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
// Generate hash of password
//const salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(ps.newPassword);
await this.userProfilesRepository.update(me.id, {

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';

View file

@ -5,7 +5,6 @@
import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { MiMeta, UserProfilesRepository } from '@/models/_.js';

View file

@ -76,11 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.gtlDisabled);
}
const [
followings,
] = me ? await Promise.all([
this.cacheService.userFollowingsCache.fetch(me.id),
]) : [undefined];
const followings = me ? await this.cacheService.userFollowingsCache.fetch(me.id) : {};
//#region Construct query
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'),

View file

@ -100,11 +100,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (me) this.queryService.generateMutedUserQueryForNotes(query, me);
if (me) this.queryService.generateBlockedUserQueryForNotes(query, me);
const [
followings,
] = me ? await Promise.all([
this.cacheService.userFollowingsCache.fetch(me.id),
]) : [undefined];
const followings = me ? await this.cacheService.userFollowingsCache.fetch(me.id) : {};
try {
if (ps.tag) {

View file

@ -66,6 +66,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
renoteId: note.id,
});
// TODO inline this into the above query
for (const note of renotes) {
if (ps.quote) {
if (note.text) this.noteDeleteService.delete(await this.usersRepository.findOneByOrFail({ id: me.id }), note, false);

View file

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/_.js';
@ -60,7 +59,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
// Generate hash of password
//const salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(ps.password);
await this.userProfilesRepository.update(req.userId, {

View file

@ -66,7 +66,8 @@ export const meta = {
// 24 calls, then 7 per second-ish (1 for each type of server info graph)
limit: {
max: 24,
type: 'bucket',
size: 24,
dripSize: 7,
dripRate: 900,
},

View file

@ -59,7 +59,8 @@ export const meta = {
// up to 50 calls @ 4 per second
limit: {
max: 50,
type: 'bucket',
size: 50,
dripRate: 250,
},
} as const;

View file

@ -23,7 +23,6 @@ import type Channel from './channel.js';
const MAX_CHANNELS_PER_CONNECTION = 32;
const MAX_SUBSCRIPTIONS_PER_CONNECTION = 512;
const MAX_CACHED_NOTES_PER_CONNECTION = 64;
/**
* Main stream connection